blob: 3b423f1b182ba9ac9c12106658493c8c1861bdfd [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Linux Build Service Account75e43952015-08-26 19:58:56 -0700572 if (snd_device == SND_DEVICE_OUT_HDMI)
573 adev->mChannelStatusSet = false;
574
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200575 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700576 audio_extn_sound_trigger_update_device_status(snd_device,
577 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530578 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800579 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 return 0;
583}
584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585static void check_usecases_codec_backend(struct audio_device *adev,
586 struct audio_usecase *uc_info,
587 snd_device_t snd_device)
588{
589 struct listnode *node;
590 struct audio_usecase *usecase;
591 bool switch_device[AUDIO_USECASE_MAX];
592 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530593 int backend_idx = DEFAULT_CODEC_BACKEND;
594 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595
596 /*
597 * This function is to make sure that all the usecases that are active on
598 * the hardware codec backend are always routed to any one device that is
599 * handled by the hardware codec.
600 * For example, if low-latency and deep-buffer usecases are currently active
601 * on speaker and out_set_parameters(headset) is received on low-latency
602 * output, then we have to make sure deep-buffer is also switched to headset,
603 * because of the limitation that both the devices cannot be enabled
604 * at the same time as they share the same backend.
605 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700606 /*
607 * This call is to check if we need to force routing for a particular stream
608 * If there is a backend configuration change for the device when a
609 * new stream starts, then ADM needs to be closed and re-opened with the new
610 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530611 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700612 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530613 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
614 snd_device);
615 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800617 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800618 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 for (i = 0; i < AUDIO_USECASE_MAX; i++)
620 switch_device[i] = false;
621
622 list_for_each(node, &adev->usecase_list) {
623 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530624
625 if (usecase == uc_info)
626 continue;
627 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
628 ALOGV("%s: backend_idx: %d,"
629 "usecase_backend_idx: %d, curr device: %s, usecase device:"
630 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530631 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800633 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700634 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
636 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530637 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530638 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700639 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700640 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641 switch_device[usecase->id] = true;
642 num_uc_to_switch++;
643 }
644 }
645
646 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700647 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530649 /* Make sure the previous devices to be disabled first and then enable the
650 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
653 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700654 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 }
656 }
657
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700662 }
663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 /* Re-route all the usecases on the shared backend other than the
666 specified usecase to new snd devices */
667 list_for_each(node, &adev->usecase_list) {
668 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530669 /* Update the out_snd_device only for the usecases that are enabled here */
670 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
671 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530672 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 }
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 }
676}
677
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700678static void check_and_route_capture_usecases(struct audio_device *adev,
679 struct audio_usecase *uc_info,
680 snd_device_t snd_device)
681{
682 struct listnode *node;
683 struct audio_usecase *usecase;
684 bool switch_device[AUDIO_USECASE_MAX];
685 int i, num_uc_to_switch = 0;
686
687 /*
688 * This function is to make sure that all the active capture usecases
689 * are always routed to the same input sound device.
690 * For example, if audio-record and voice-call usecases are currently
691 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
692 * is received for voice call then we have to make sure that audio-record
693 * usecase is also switched to earpiece i.e. voice-dmic-ef,
694 * because of the limitation that two devices cannot be enabled
695 * at the same time if they share the same backend.
696 */
697 for (i = 0; i < AUDIO_USECASE_MAX; i++)
698 switch_device[i] = false;
699
700 list_for_each(node, &adev->usecase_list) {
701 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800702 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700704 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700705 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
706 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700707 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700708 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
709 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700710 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 switch_device[usecase->id] = true;
713 num_uc_to_switch++;
714 }
715 }
716
717 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530720 /* Make sure the previous devices to be disabled first and then enable the
721 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700722 list_for_each(node, &adev->usecase_list) {
723 usecase = node_to_item(node, struct audio_usecase, list);
724 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800726 }
727 }
728
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 }
734 }
735
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 /* Re-route all the usecases on the shared backend other than the
737 specified usecase to new snd devices */
738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
740 /* Update the in_snd_device only before enabling the audio route */
741 if (switch_device[usecase->id] ) {
742 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800743 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530744 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 }
746 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700747 }
748}
749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700751static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700753 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700754 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800755
756 switch (channels) {
757 /*
758 * Do not handle stereo output in Multi-channel cases
759 * Stereo case is handled in normal playback path
760 */
761 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 break;
769 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700770 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777 break;
778 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700779 ALOGE("HDMI does not support multi channel playback");
780 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781 break;
782 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784}
785
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800786audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
787 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700788{
789 struct audio_usecase *usecase;
790 struct listnode *node;
791
792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800794 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795 ALOGV("%s: usecase id %d", __func__, usecase->id);
796 return usecase->id;
797 }
798 }
799 return USECASE_INVALID;
800}
801
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700802struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804{
805 struct audio_usecase *usecase;
806 struct listnode *node;
807
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 if (usecase->id == uc_id)
811 return usecase;
812 }
813 return NULL;
814}
815
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700816int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 snd_device_t out_snd_device = SND_DEVICE_NONE;
819 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 struct audio_usecase *usecase = NULL;
821 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800822 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800823 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800824 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800825 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 usecase = get_usecase_from_list(adev, uc_id);
829 if (usecase == NULL) {
830 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
831 return -EINVAL;
832 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800834 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800835 (usecase->type == VOIP_CALL) ||
836 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700837 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800838 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700839 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 usecase->devices = usecase->stream.out->devices;
841 } else {
842 /*
843 * If the voice call is active, use the sound devices of voice call usecase
844 * so that it would not result any device switch. All the usecases will
845 * be switched to new device when select_devices() is called for voice call
846 * usecase. This is to avoid switching devices for voice call when
847 * check_usecases_codec_backend() is called below.
848 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700849 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700850 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800851 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700852 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
853 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700854 in_snd_device = vc_usecase->in_snd_device;
855 out_snd_device = vc_usecase->out_snd_device;
856 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800857 } else if (voice_extn_compress_voip_is_active(adev)) {
858 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530860 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700861 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800862 in_snd_device = voip_usecase->in_snd_device;
863 out_snd_device = voip_usecase->out_snd_device;
864 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800865 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800866 hfp_ucid = audio_extn_hfp_get_usecase();
867 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800869 in_snd_device = hfp_usecase->in_snd_device;
870 out_snd_device = hfp_usecase->out_snd_device;
871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 }
873 if (usecase->type == PCM_PLAYBACK) {
874 usecase->devices = usecase->stream.out->devices;
875 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700876 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700877 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800878 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700879 if (usecase->stream.out == adev->primary_output &&
880 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800881 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700882 select_devices(adev, adev->active_input->usecase);
883 }
884 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 } else if (usecase->type == PCM_CAPTURE) {
886 usecase->devices = usecase->stream.in->device;
887 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700888 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530890 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
891 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
892 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
893 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700894 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800895 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
897 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700898 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700899 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902 }
903
904 if (out_snd_device == usecase->out_snd_device &&
905 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906 return 0;
907 }
908
sangwoobc677242013-08-08 16:53:43 +0900909 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700910 out_snd_device, platform_get_snd_device_name(out_snd_device),
911 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 /*
914 * Limitation: While in call, to do a device switch we need to disable
915 * and enable both RX and TX devices though one of them is same as current
916 * device.
917 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700918 if ((usecase->type == VOICE_CALL) &&
919 (usecase->in_snd_device != SND_DEVICE_NONE) &&
920 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700921 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700922 /* Disable sidetone only if voice call already exists */
923 if (voice_is_call_state_active(adev))
924 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800925 }
926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /* Disable current sound devices */
928 if (usecase->out_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->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800931 }
932
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700934 disable_audio_route(adev, usecase);
935 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800936 }
937
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800938 /* Applicable only on the targets that has external modem.
939 * New device information should be sent to modem before enabling
940 * the devices to reduce in-call device switch time.
941 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700942 if ((usecase->type == VOICE_CALL) &&
943 (usecase->in_snd_device != SND_DEVICE_NONE) &&
944 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800945 status = platform_switch_voice_call_enable_device_config(adev->platform,
946 out_snd_device,
947 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700948 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 /* Enable new sound devices */
951 if (out_snd_device != SND_DEVICE_NONE) {
952 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
953 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700954 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955 }
956
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 if (in_snd_device != SND_DEVICE_NONE) {
958 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700959 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961
Avinash Vaish71a8b972014-07-24 15:36:33 +0530962 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700963 status = platform_switch_voice_call_device_post(adev->platform,
964 out_snd_device,
965 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530966 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700967 /* Enable sidetone only if voice call already exists */
968 if (voice_is_call_state_active(adev))
969 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530970 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800971
sangwoo170731f2013-06-08 15:36:36 +0900972 usecase->in_snd_device = in_snd_device;
973 usecase->out_snd_device = out_snd_device;
974
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530975 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700976 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530977 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700978 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530979 usecase->stream.out->flags,
980 usecase->stream.out->format,
981 usecase->stream.out->sample_rate,
982 usecase->stream.out->bit_width,
983 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700984 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530985 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700986
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700987 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900988
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800989 /* Applicable only on the targets that has external modem.
990 * Enable device command should be sent to modem only after
991 * enabling voice call mixer controls
992 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700993 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800994 status = platform_switch_voice_call_usecase_route_post(adev->platform,
995 out_snd_device,
996 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530997 ALOGD("%s: done",__func__);
998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 return status;
1000}
1001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002static int stop_input_stream(struct stream_in *in)
1003{
1004 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 struct audio_usecase *uc_info;
1006 struct audio_device *adev = in->dev;
1007
Eric Laurentc8400632013-02-14 19:04:54 -08001008 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001009
Eric Laurent994a6932013-07-17 11:51:42 -07001010 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 uc_info = get_usecase_from_list(adev, in->usecase);
1013 if (uc_info == NULL) {
1014 ALOGE("%s: Could not find the usecase (%d) in the list",
1015 __func__, in->usecase);
1016 return -EINVAL;
1017 }
1018
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001019 /* Close in-call recording streams */
1020 voice_check_and_stop_incall_rec_usecase(adev, in);
1021
Eric Laurent150dbfe2013-02-27 14:31:02 -08001022 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001023 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024
1025 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001026 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001028 list_remove(&uc_info->list);
1029 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030
Eric Laurent994a6932013-07-17 11:51:42 -07001031 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 return ret;
1033}
1034
1035int start_input_stream(struct stream_in *in)
1036{
1037 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001038 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 struct audio_usecase *uc_info;
1040 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301041 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301043 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1044 if (get_usecase_from_list(adev, usecase) == NULL)
1045 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301046 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1047 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001048
Naresh Tanniru80659832014-06-04 18:17:56 +05301049
1050 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301051 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301052 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301053 goto error_config;
1054 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301055
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001056 /* Check if source matches incall recording usecase criteria */
1057 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1058 if (ret)
1059 goto error_config;
1060 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301061 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1062
1063 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1064 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1065 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1066 goto error_config;
1067 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001068
Eric Laurentb23d5282013-05-14 15:27:20 -07001069 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 if (in->pcm_device_id < 0) {
1071 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1072 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001073 ret = -EINVAL;
1074 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076
1077 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001079
1080 if (!uc_info) {
1081 ret = -ENOMEM;
1082 goto error_config;
1083 }
1084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 uc_info->id = in->usecase;
1086 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001087 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 uc_info->devices = in->device;
1089 uc_info->in_snd_device = SND_DEVICE_NONE;
1090 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001092 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301093 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095
Eric Laurentc8400632013-02-14 19:04:54 -08001096 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001097 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1098
1099 unsigned int flags = PCM_IN;
1100 unsigned int pcm_open_retry_count = 0;
1101
1102 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1103 flags |= PCM_MMAP | PCM_NOIRQ;
1104 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1105 }
1106
1107 while (1) {
1108 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1109 flags, &in->config);
1110 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1111 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1112 if (in->pcm != NULL) {
1113 pcm_close(in->pcm);
1114 in->pcm = NULL;
1115 }
1116 if (pcm_open_retry_count-- == 0) {
1117 ret = -EIO;
1118 goto error_open;
1119 }
1120 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1121 continue;
1122 }
1123 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301125 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301126
Eric Laurent994a6932013-07-17 11:51:42 -07001127 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001128 return ret;
1129
1130error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301132 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001133
1134error_config:
1135 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001137
1138 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139}
1140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001141/* must be called with out->lock locked */
1142static int send_offload_cmd_l(struct stream_out* out, int command)
1143{
1144 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1145
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001146 if (!cmd) {
1147 ALOGE("failed to allocate mem for command 0x%x", command);
1148 return -ENOMEM;
1149 }
1150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001151 ALOGVV("%s %d", __func__, command);
1152
1153 cmd->cmd = command;
1154 list_add_tail(&out->offload_cmd_list, &cmd->node);
1155 pthread_cond_signal(&out->offload_cond);
1156 return 0;
1157}
1158
1159/* must be called iwth out->lock locked */
1160static void stop_compressed_output_l(struct stream_out *out)
1161{
1162 out->offload_state = OFFLOAD_STATE_IDLE;
1163 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001164 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001165 if (out->compr != NULL) {
1166 compress_stop(out->compr);
1167 while (out->offload_thread_blocked) {
1168 pthread_cond_wait(&out->cond, &out->lock);
1169 }
1170 }
1171}
1172
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001173bool is_offload_usecase(audio_usecase_t uc_id)
1174{
1175 unsigned int i;
1176 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1177 if (uc_id == offload_usecases[i])
1178 return true;
1179 }
1180 return false;
1181}
1182
1183static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1184{
1185 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1186 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1187 char value[PROPERTY_VALUE_MAX] = {0};
1188
1189 property_get("audio.offload.multiple.enabled", value, NULL);
1190 if (!(atoi(value) || !strncmp("true", value, 4)))
1191 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1192
1193 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1194 for (i = 0; i < num_usecase; i++) {
1195 if (!(adev->offload_usecases_state & (0x1<<i))) {
1196 adev->offload_usecases_state |= 0x1 << i;
1197 ret = offload_usecases[i];
1198 break;
1199 }
1200 }
1201 ALOGV("%s: offload usecase is %d", __func__, ret);
1202 return ret;
1203}
1204
1205static void free_offload_usecase(struct audio_device *adev,
1206 audio_usecase_t uc_id)
1207{
1208 unsigned int i;
1209 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1210 if (offload_usecases[i] == uc_id) {
1211 adev->offload_usecases_state &= ~(0x1<<i);
1212 break;
1213 }
1214 }
1215 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1216}
1217
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001218static void *offload_thread_loop(void *context)
1219{
1220 struct stream_out *out = (struct stream_out *) context;
1221 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001222 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001224 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1225 set_sched_policy(0, SP_FOREGROUND);
1226 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1227
1228 ALOGV("%s", __func__);
1229 pthread_mutex_lock(&out->lock);
1230 for (;;) {
1231 struct offload_cmd *cmd = NULL;
1232 stream_callback_event_t event;
1233 bool send_callback = false;
1234
1235 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1236 __func__, list_empty(&out->offload_cmd_list),
1237 out->offload_state);
1238 if (list_empty(&out->offload_cmd_list)) {
1239 ALOGV("%s SLEEPING", __func__);
1240 pthread_cond_wait(&out->offload_cond, &out->lock);
1241 ALOGV("%s RUNNING", __func__);
1242 continue;
1243 }
1244
1245 item = list_head(&out->offload_cmd_list);
1246 cmd = node_to_item(item, struct offload_cmd, node);
1247 list_remove(item);
1248
1249 ALOGVV("%s STATE %d CMD %d out->compr %p",
1250 __func__, out->offload_state, cmd->cmd, out->compr);
1251
1252 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1253 free(cmd);
1254 break;
1255 }
1256
1257 if (out->compr == NULL) {
1258 ALOGE("%s: Compress handle is NULL", __func__);
1259 pthread_cond_signal(&out->cond);
1260 continue;
1261 }
1262 out->offload_thread_blocked = true;
1263 pthread_mutex_unlock(&out->lock);
1264 send_callback = false;
1265 switch(cmd->cmd) {
1266 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001267 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001268 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001269 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001270 send_callback = true;
1271 event = STREAM_CBK_EVENT_WRITE_READY;
1272 break;
1273 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001274 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301275 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001276 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301277 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001278 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301279 if (ret < 0)
1280 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301281 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301282 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001283 compress_drain(out->compr);
1284 else
1285 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301286 if (ret != -ENETRESET) {
1287 send_callback = true;
1288 event = STREAM_CBK_EVENT_DRAIN_READY;
1289 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1290 } else
1291 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 break;
1293 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001294 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001296 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001297 send_callback = true;
1298 event = STREAM_CBK_EVENT_DRAIN_READY;
1299 break;
1300 default:
1301 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1302 break;
1303 }
1304 pthread_mutex_lock(&out->lock);
1305 out->offload_thread_blocked = false;
1306 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001307 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001308 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001309 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001310 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001311 free(cmd);
1312 }
1313
1314 pthread_cond_signal(&out->cond);
1315 while (!list_empty(&out->offload_cmd_list)) {
1316 item = list_head(&out->offload_cmd_list);
1317 list_remove(item);
1318 free(node_to_item(item, struct offload_cmd, node));
1319 }
1320 pthread_mutex_unlock(&out->lock);
1321
1322 return NULL;
1323}
1324
1325static int create_offload_callback_thread(struct stream_out *out)
1326{
1327 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1328 list_init(&out->offload_cmd_list);
1329 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1330 offload_thread_loop, out);
1331 return 0;
1332}
1333
1334static int destroy_offload_callback_thread(struct stream_out *out)
1335{
1336 pthread_mutex_lock(&out->lock);
1337 stop_compressed_output_l(out);
1338 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1339
1340 pthread_mutex_unlock(&out->lock);
1341 pthread_join(out->offload_thread, (void **) NULL);
1342 pthread_cond_destroy(&out->offload_cond);
1343
1344 return 0;
1345}
1346
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347static bool allow_hdmi_channel_config(struct audio_device *adev)
1348{
1349 struct listnode *node;
1350 struct audio_usecase *usecase;
1351 bool ret = true;
1352
1353 list_for_each(node, &adev->usecase_list) {
1354 usecase = node_to_item(node, struct audio_usecase, list);
1355 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1356 /*
1357 * If voice call is already existing, do not proceed further to avoid
1358 * disabling/enabling both RX and TX devices, CSD calls, etc.
1359 * Once the voice call done, the HDMI channels can be configured to
1360 * max channels of remaining use cases.
1361 */
1362 if (usecase->id == USECASE_VOICE_CALL) {
1363 ALOGD("%s: voice call is active, no change in HDMI channels",
1364 __func__);
1365 ret = false;
1366 break;
1367 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1368 ALOGD("%s: multi channel playback is active, "
1369 "no change in HDMI channels", __func__);
1370 ret = false;
1371 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001372 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001373 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001374 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1375 ", no change in HDMI channels", __func__,
1376 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001377 ret = false;
1378 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001379 }
1380 }
1381 }
1382 return ret;
1383}
1384
1385static int check_and_set_hdmi_channels(struct audio_device *adev,
1386 unsigned int channels)
1387{
1388 struct listnode *node;
1389 struct audio_usecase *usecase;
1390
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001391 unsigned int supported_channels = platform_edid_get_max_channels(
1392 adev->platform);
1393 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 /* Check if change in HDMI channel config is allowed */
1395 if (!allow_hdmi_channel_config(adev))
1396 return 0;
1397
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001398 if (channels > supported_channels)
1399 channels = supported_channels;
1400
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001402 ALOGD("%s: Requested channels are same as current channels(%d)",
1403 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001404 return 0;
1405 }
1406
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001407 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001408 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001409 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001410 adev->cur_hdmi_channels = channels;
1411
1412 /*
1413 * Deroute all the playback streams routed to HDMI so that
1414 * the back end is deactivated. Note that backend will not
1415 * be deactivated if any one stream is connected to it.
1416 */
1417 list_for_each(node, &adev->usecase_list) {
1418 usecase = node_to_item(node, struct audio_usecase, list);
1419 if (usecase->type == PCM_PLAYBACK &&
1420 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001421 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001422 }
1423 }
1424
1425 /*
1426 * Enable all the streams disabled above. Now the HDMI backend
1427 * will be activated with new channel configuration
1428 */
1429 list_for_each(node, &adev->usecase_list) {
1430 usecase = node_to_item(node, struct audio_usecase, list);
1431 if (usecase->type == PCM_PLAYBACK &&
1432 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001433 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001434 }
1435 }
1436
1437 return 0;
1438}
1439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440static int stop_output_stream(struct stream_out *out)
1441{
1442 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 struct audio_usecase *uc_info;
1444 struct audio_device *adev = out->dev;
1445
Eric Laurent994a6932013-07-17 11:51:42 -07001446 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001447 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 uc_info = get_usecase_from_list(adev, out->usecase);
1449 if (uc_info == NULL) {
1450 ALOGE("%s: Could not find the usecase (%d) in the list",
1451 __func__, out->usecase);
1452 return -EINVAL;
1453 }
1454
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001455 if (is_offload_usecase(out->usecase) &&
1456 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001457 if (adev->visualizer_stop_output != NULL)
1458 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001459
1460 audio_extn_dts_remove_state_notifier_node(out->usecase);
1461
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001462 if (adev->offload_effects_stop_output != NULL)
1463 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1464 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001465
Eric Laurent150dbfe2013-02-27 14:31:02 -08001466 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001467 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468
1469 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001470 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001472 list_remove(&uc_info->list);
1473 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001475 if (is_offload_usecase(out->usecase) &&
1476 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1477 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1478 ALOGV("Disable passthrough , reset mixer to pcm");
1479 /* NO_PASSTHROUGH */
1480 out->compr_config.codec->compr_passthr = 0;
1481 audio_extn_dolby_set_hdmi_config(adev, out);
1482 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1483 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001484 /* Must be called after removing the usecase from list */
1485 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1486 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1487
Eric Laurent994a6932013-07-17 11:51:42 -07001488 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 return ret;
1490}
1491
1492int start_output_stream(struct stream_out *out)
1493{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001495 int sink_channels = 0;
1496 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 struct audio_usecase *uc_info;
1498 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301499 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001501 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1502 ret = -EINVAL;
1503 goto error_config;
1504 }
1505
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301506 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1507 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1508 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301509
Naresh Tanniru80659832014-06-04 18:17:56 +05301510 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301511 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301512 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301513 goto error_config;
1514 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301515
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 if (out->pcm_device_id < 0) {
1518 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1519 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001520 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001521 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522 }
1523
1524 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001525
1526 if (!uc_info) {
1527 ret = -ENOMEM;
1528 goto error_config;
1529 }
1530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 uc_info->id = out->usecase;
1532 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001533 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 uc_info->devices = out->devices;
1535 uc_info->in_snd_device = SND_DEVICE_NONE;
1536 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001537 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001538 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001539 if (is_offload_usecase(out->usecase)) {
1540 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001541 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1542 }
1543 }
Mingming Yin9c041392014-05-01 15:37:31 -07001544 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1545 if (!strncmp("true", prop_value, 4)) {
1546 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001547 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1548 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001549 check_and_set_hdmi_channels(adev, sink_channels);
1550 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001551 if (is_offload_usecase(out->usecase)) {
1552 unsigned int ch_count = out->compr_config.codec->ch_in;
1553 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1554 /* backend channel config for passthrough stream is stereo */
1555 ch_count = 2;
1556 check_and_set_hdmi_channels(adev, ch_count);
1557 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001558 check_and_set_hdmi_channels(adev, out->config.channels);
1559 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001561 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001562 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 select_devices(adev, out->usecase);
1565
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001566 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1567 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001568 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001569 unsigned int flags = PCM_OUT;
1570 unsigned int pcm_open_retry_count = 0;
1571 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1572 flags |= PCM_MMAP | PCM_NOIRQ;
1573 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1574 } else
1575 flags |= PCM_MONOTONIC;
1576
1577 while (1) {
1578 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1579 flags, &out->config);
1580 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1581 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1582 if (out->pcm != NULL) {
1583 pcm_close(out->pcm);
1584 out->pcm = NULL;
1585 }
1586 if (pcm_open_retry_count-- == 0) {
1587 ret = -EIO;
1588 goto error_open;
1589 }
1590 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1591 continue;
1592 }
1593 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001594 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001595 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1596 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001597 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001598 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1599 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001601 out->compr = compress_open(adev->snd_card,
1602 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 COMPRESS_IN, &out->compr_config);
1604 if (out->compr && !is_compress_ready(out->compr)) {
1605 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1606 compress_close(out->compr);
1607 out->compr = NULL;
1608 ret = -EIO;
1609 goto error_open;
1610 }
1611 if (out->offload_callback)
1612 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001613
Fred Oh3f43e742015-03-04 18:42:34 -08001614 /* Since small bufs uses blocking writes, a write will be blocked
1615 for the default max poll time (20s) in the event of an SSR.
1616 Reduce the poll time to observe and deal with SSR faster.
1617 */
1618 if (out->use_small_bufs) {
1619 compress_set_max_poll_wait(out->compr, 1000);
1620 }
1621
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001622 audio_extn_dts_create_state_notifier_node(out->usecase);
1623 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1624 popcount(out->channel_mask),
1625 out->playback_started);
1626
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001627#ifdef DS1_DOLBY_DDP_ENABLED
1628 if (audio_extn_is_dolby_format(out->format))
1629 audio_extn_dolby_send_ddp_endp_params(adev);
1630#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001631 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1632 if (adev->visualizer_start_output != NULL)
1633 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1634 if (adev->offload_effects_start_output != NULL)
1635 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001636 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 }
Eric Laurent994a6932013-07-17 11:51:42 -07001639 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001643error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001644 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645}
1646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647static int check_input_parameters(uint32_t sample_rate,
1648 audio_format_t format,
1649 int channel_count)
1650{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001651 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001653 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001654 !voice_extn_compress_voip_is_format_supported(format) &&
1655 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001656
1657 switch (channel_count) {
1658 case 1:
1659 case 2:
1660 case 6:
1661 break;
1662 default:
1663 ret = -EINVAL;
1664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665
1666 switch (sample_rate) {
1667 case 8000:
1668 case 11025:
1669 case 12000:
1670 case 16000:
1671 case 22050:
1672 case 24000:
1673 case 32000:
1674 case 44100:
1675 case 48000:
1676 break;
1677 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001678 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 }
1680
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682}
1683
1684static size_t get_input_buffer_size(uint32_t sample_rate,
1685 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001686 int channel_count,
1687 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688{
1689 size_t size = 0;
1690
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001691 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1692 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001694 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001695 if (is_low_latency)
1696 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001697 /* ToDo: should use frame_size computed based on the format and
1698 channel_count here. */
1699 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001701 /* make sure the size is multiple of 32 bytes
1702 * At 48 kHz mono 16-bit PCM:
1703 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1704 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1705 */
1706 size += 0x1f;
1707 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001708
1709 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710}
1711
1712static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1713{
1714 struct stream_out *out = (struct stream_out *)stream;
1715
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717}
1718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001719static int out_set_sample_rate(struct audio_stream *stream __unused,
1720 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721{
1722 return -ENOSYS;
1723}
1724
1725static size_t out_get_buffer_size(const struct audio_stream *stream)
1726{
1727 struct stream_out *out = (struct stream_out *)stream;
1728
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001729 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001731 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1732 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001734 return out->config.period_size *
1735 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736}
1737
1738static uint32_t out_get_channels(const struct audio_stream *stream)
1739{
1740 struct stream_out *out = (struct stream_out *)stream;
1741
1742 return out->channel_mask;
1743}
1744
1745static audio_format_t out_get_format(const struct audio_stream *stream)
1746{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747 struct stream_out *out = (struct stream_out *)stream;
1748
1749 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750}
1751
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001752static int out_set_format(struct audio_stream *stream __unused,
1753 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754{
1755 return -ENOSYS;
1756}
1757
1758static int out_standby(struct audio_stream *stream)
1759{
1760 struct stream_out *out = (struct stream_out *)stream;
1761 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301763 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1764 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001765 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1766 /* Ignore standby in case of voip call because the voip output
1767 * stream is closed in adev_close_output_stream()
1768 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301769 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001770 return 0;
1771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001775 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001777 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 if (out->pcm) {
1779 pcm_close(out->pcm);
1780 out->pcm = NULL;
1781 }
1782 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001783 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001785 out->gapless_mdata.encoder_delay = 0;
1786 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001787 if (out->compr != NULL) {
1788 compress_close(out->compr);
1789 out->compr = NULL;
1790 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001793 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 }
1795 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001796 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 return 0;
1798}
1799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001800static int out_dump(const struct audio_stream *stream __unused,
1801 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802{
1803 return 0;
1804}
1805
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001806static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1807{
1808 int ret = 0;
1809 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301810 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001811
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001813 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 return -EINVAL;
1815 }
1816
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1818 if (ret >= 0) {
1819 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1820 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1821 ALOGV("ADTS format is set in offload mode");
1822 }
Yadav Anamikafbcef792015-08-19 16:15:00 +05301823 out->send_new_metadata = 1;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001824 }
1825
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301826 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001827
Yadav Anamikafbcef792015-08-19 16:15:00 +05301828 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1829 if(ret >= 0)
1830 is_meta_data_params = true;
1831 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1832 if(ret >= 0)
1833 is_meta_data_params = true;
1834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1835 if(ret >= 0)
1836 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1838 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301839 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301840 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001841 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001842 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1843 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301844 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301845 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001846 }
1847
Yadav Anamikafbcef792015-08-19 16:15:00 +05301848 if(!is_meta_data_params) {
1849 ALOGV("%s: Not gapless meta data params", __func__);
1850 return 0;
1851 }
1852 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853 ALOGV("%s new encoder delay %u and padding %u", __func__,
1854 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1855
1856 return 0;
1857}
1858
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001859static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1860{
1861 return out == adev->primary_output || out == adev->voice_tx_output;
1862}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1865{
1866 struct stream_out *out = (struct stream_out *)stream;
1867 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001868 struct audio_usecase *usecase;
1869 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 struct str_parms *parms;
1871 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001872 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001873 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874
sangwoobc677242013-08-08 16:53:43 +09001875 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301878 if (!parms)
1879 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001880 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1881 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001884 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301887 * When HDMI cable is unplugged/usb hs is disconnected the
1888 * music playback is paused and the policy manager sends routing=0
1889 * But the audioflingercontinues to write data until standby time
1890 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 * Avoid this by routing audio to speaker until standby.
1892 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301893 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1894 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001896 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1897 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 }
1899
1900 /*
1901 * select_devices() call below switches all the usecases on the same
1902 * backend to the new device. Refer to check_usecases_codec_backend() in
1903 * the select_devices(). But how do we undo this?
1904 *
1905 * For example, music playback is active on headset (deep-buffer usecase)
1906 * and if we go to ringtones and select a ringtone, low-latency usecase
1907 * will be started on headset+speaker. As we can't enable headset+speaker
1908 * and headset devices at the same time, select_devices() switches the music
1909 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1910 * So when the ringtone playback is completed, how do we undo the same?
1911 *
1912 * We are relying on the out_set_parameters() call on deep-buffer output,
1913 * once the ringtone playback is ended.
1914 * NOTE: We should not check if the current devices are same as new devices.
1915 * Because select_devices() must be called to switch back the music
1916 * playback to headset.
1917 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001918 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 out->devices = val;
1920
1921 if (!out->standby)
1922 select_devices(adev, out->usecase);
1923
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001924 if (output_drives_call(adev, out)) {
1925 if(!voice_is_in_call(adev)) {
1926 if (adev->mode == AUDIO_MODE_IN_CALL) {
1927 adev->current_call_output = out;
1928 ret = voice_start_call(adev);
1929 }
1930 } else {
1931 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001932 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001933 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001934 }
1935 }
1936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001938 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001940
1941 if (out == adev->primary_output) {
1942 pthread_mutex_lock(&adev->lock);
1943 audio_extn_set_parameters(adev, parms);
1944 pthread_mutex_unlock(&adev->lock);
1945 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001946 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001947 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001948 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001949
1950 audio_extn_dts_create_state_notifier_node(out->usecase);
1951 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1952 popcount(out->channel_mask),
1953 out->playback_started);
1954
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001955 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001956 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301959error:
Eric Laurent994a6932013-07-17 11:51:42 -07001960 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 return ret;
1962}
1963
1964static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1965{
1966 struct stream_out *out = (struct stream_out *)stream;
1967 struct str_parms *query = str_parms_create_str(keys);
1968 char *str;
1969 char value[256];
1970 struct str_parms *reply = str_parms_create();
1971 size_t i, j;
1972 int ret;
1973 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001974
1975 if (!query || !reply) {
1976 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1977 return NULL;
1978 }
1979
Eric Laurent994a6932013-07-17 11:51:42 -07001980 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1982 if (ret >= 0) {
1983 value[0] = '\0';
1984 i = 0;
1985 while (out->supported_channel_masks[i] != 0) {
1986 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1987 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1988 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001989 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001991 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992 first = false;
1993 break;
1994 }
1995 }
1996 i++;
1997 }
1998 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1999 str = str_parms_to_str(reply);
2000 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002001 voice_extn_out_get_parameters(out, query, reply);
2002 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002003 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002004 free(str);
2005 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002008
2009 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2010 if (ret >= 0) {
2011 value[0] = '\0';
2012 i = 0;
2013 first = true;
2014 while (out->supported_formats[i] != 0) {
2015 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2016 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2017 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002018 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002019 }
2020 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2021 first = false;
2022 break;
2023 }
2024 }
2025 i++;
2026 }
2027 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2028 str = str_parms_to_str(reply);
2029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 str_parms_destroy(query);
2031 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002032 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 return str;
2034}
2035
2036static uint32_t out_get_latency(const struct audio_stream_out *stream)
2037{
2038 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002039 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040
Alexy Josephaa54c872014-12-03 02:46:47 -08002041 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002042 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002043 } else {
2044 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002045 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002046 }
2047
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302048 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002049 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050}
2051
2052static int out_set_volume(struct audio_stream_out *stream, float left,
2053 float right)
2054{
Eric Laurenta9024de2013-04-04 09:19:12 -07002055 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 int volume[2];
2057
Eric Laurenta9024de2013-04-04 09:19:12 -07002058 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2059 /* only take left channel into account: the API is for stereo anyway */
2060 out->muted = (left == 0.0f);
2061 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002062 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002063 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2064 /*
2065 * Set mute or umute on HDMI passthrough stream.
2066 * Only take left channel into account.
2067 * Mute is 0 and unmute 1
2068 */
2069 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2070 } else {
2071 char mixer_ctl_name[128];
2072 struct audio_device *adev = out->dev;
2073 struct mixer_ctl *ctl;
2074 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002075 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002077 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2078 "Compress Playback %d Volume", pcm_device_id);
2079 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2080 if (!ctl) {
2081 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2082 __func__, mixer_ctl_name);
2083 return -EINVAL;
2084 }
2085 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2086 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2087 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2088 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002090 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 return -ENOSYS;
2093}
2094
2095static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2096 size_t bytes)
2097{
2098 struct stream_out *out = (struct stream_out *)stream;
2099 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302100 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002101 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302104
Naresh Tanniru80659832014-06-04 18:17:56 +05302105 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002106 // increase written size during SSR to avoid mismatch
2107 // with the written frames count in AF
2108 if (!is_offload_usecase(out->usecase))
2109 out->written += bytes / (out->config.channels * sizeof(short));
2110
Naresh Tanniru80659832014-06-04 18:17:56 +05302111 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302112 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302113 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302114 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002115 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302116 //during SSR for compress usecase we should return error to flinger
2117 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2118 pthread_mutex_unlock(&out->lock);
2119 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302120 }
2121 }
2122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002124 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002125 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002126 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2127 ret = voice_extn_compress_voip_start_output_stream(out);
2128 else
2129 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002130 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002133 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 goto exit;
2135 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302138 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2139 setChannelStatus(out, buffer, bytes);
2140 adev->mChannelStatusSet = true;
2141 }
2142
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002143 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002144 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002145 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002146 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002147 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2148 out->send_new_metadata = 0;
2149 }
2150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302152 if (ret < 0)
2153 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002155 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302156 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302158 } else if (-ENETRESET == ret) {
2159 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2160 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2161 pthread_mutex_unlock(&out->lock);
2162 out_standby(&out->stream.common);
2163 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002167 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 out->playback_started = 1;
2169 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002170
2171 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2172 popcount(out->channel_mask),
2173 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 }
2175 pthread_mutex_unlock(&out->lock);
2176 return ret;
2177 } else {
2178 if (out->pcm) {
2179 if (out->muted)
2180 memset((void *)buffer, 0, bytes);
2181 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002182 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2183 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2184 else
2185 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302186 if (ret < 0)
2187 ret = -errno;
2188 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002189 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 }
2192
2193exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302194 /* ToDo: There may be a corner case when SSR happens back to back during
2195 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302196 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302197 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302198 }
2199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 pthread_mutex_unlock(&out->lock);
2201
2202 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002203 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002204 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302205 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302206 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302207 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302208 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302209 out->standby = true;
2210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002212 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302213 out_get_sample_rate(&out->stream.common));
2214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 }
2216 return bytes;
2217}
2218
2219static int out_get_render_position(const struct audio_stream_out *stream,
2220 uint32_t *dsp_frames)
2221{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302223 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002224
2225 if (dsp_frames == NULL)
2226 return -EINVAL;
2227
2228 *dsp_frames = 0;
2229 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002230 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 pthread_mutex_lock(&out->lock);
2232 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302233 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302235 if (ret < 0)
2236 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 ALOGVV("%s rendered frames %d sample_rate %d",
2238 __func__, *dsp_frames, out->sample_rate);
2239 }
2240 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302241 if (-ENETRESET == ret) {
2242 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2243 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2244 return -EINVAL;
2245 } else if(ret < 0) {
2246 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2247 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302248 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2249 /*
2250 * Handle corner case where compress session is closed during SSR
2251 * and timestamp is queried
2252 */
2253 ALOGE(" ERROR: sound card not active, return error");
2254 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302255 } else {
2256 return 0;
2257 }
Zhou Song32a556e2015-05-05 10:46:56 +08002258 } else if (audio_is_linear_pcm(out->format)) {
2259 *dsp_frames = out->written;
2260 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002261 } else
2262 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263}
2264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002265static int out_add_audio_effect(const struct audio_stream *stream __unused,
2266 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267{
2268 return 0;
2269}
2270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002271static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2272 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273{
2274 return 0;
2275}
2276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002277static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2278 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279{
2280 return -EINVAL;
2281}
2282
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002283static int out_get_presentation_position(const struct audio_stream_out *stream,
2284 uint64_t *frames, struct timespec *timestamp)
2285{
2286 struct stream_out *out = (struct stream_out *)stream;
2287 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002288 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002289
2290 pthread_mutex_lock(&out->lock);
2291
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002292 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002293 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302294 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002295 &out->sample_rate);
2296 ALOGVV("%s rendered frames %ld sample_rate %d",
2297 __func__, dsp_frames, out->sample_rate);
2298 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302299 if (ret < 0)
2300 ret = -errno;
2301 if (-ENETRESET == ret) {
2302 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2303 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2304 ret = -EINVAL;
2305 } else
2306 ret = 0;
2307
Eric Laurent949a0892013-09-20 09:20:13 -07002308 /* this is the best we can do */
2309 clock_gettime(CLOCK_MONOTONIC, timestamp);
2310 }
2311 } else {
2312 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002313 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002314 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2315 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002316 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002317 // This adjustment accounts for buffering after app processor.
2318 // It is based on estimated DSP latency per use case, rather than exact.
2319 signed_frames -=
2320 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2321
Eric Laurent949a0892013-09-20 09:20:13 -07002322 // It would be unusual for this value to be negative, but check just in case ...
2323 if (signed_frames >= 0) {
2324 *frames = signed_frames;
2325 ret = 0;
2326 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002327 }
2328 }
2329 }
2330
2331 pthread_mutex_unlock(&out->lock);
2332
2333 return ret;
2334}
2335
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336static int out_set_callback(struct audio_stream_out *stream,
2337 stream_callback_t callback, void *cookie)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340
2341 ALOGV("%s", __func__);
2342 pthread_mutex_lock(&out->lock);
2343 out->offload_callback = callback;
2344 out->offload_cookie = cookie;
2345 pthread_mutex_unlock(&out->lock);
2346 return 0;
2347}
2348
2349static int out_pause(struct audio_stream_out* stream)
2350{
2351 struct stream_out *out = (struct stream_out *)stream;
2352 int status = -ENOSYS;
2353 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002354 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002355 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 pthread_mutex_lock(&out->lock);
2357 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302358 struct audio_device *adev = out->dev;
2359 int snd_scard_state = get_snd_card_state(adev);
2360
2361 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2362 status = compress_pause(out->compr);
2363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002365
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302366 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002367 audio_extn_dts_notify_playback_state(out->usecase, 0,
2368 out->sample_rate, popcount(out->channel_mask),
2369 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 }
2371 pthread_mutex_unlock(&out->lock);
2372 }
2373 return status;
2374}
2375
2376static int out_resume(struct audio_stream_out* stream)
2377{
2378 struct stream_out *out = (struct stream_out *)stream;
2379 int status = -ENOSYS;
2380 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002381 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002382 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 status = 0;
2384 pthread_mutex_lock(&out->lock);
2385 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302386 struct audio_device *adev = out->dev;
2387 int snd_scard_state = get_snd_card_state(adev);
2388
2389 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2390 status = compress_resume(out->compr);
2391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002393
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302394 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002395 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2396 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 }
2398 pthread_mutex_unlock(&out->lock);
2399 }
2400 return status;
2401}
2402
2403static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2404{
2405 struct stream_out *out = (struct stream_out *)stream;
2406 int status = -ENOSYS;
2407 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002408 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 pthread_mutex_lock(&out->lock);
2410 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2411 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2412 else
2413 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2414 pthread_mutex_unlock(&out->lock);
2415 }
2416 return status;
2417}
2418
2419static int out_flush(struct audio_stream_out* stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002423 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002424 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 pthread_mutex_lock(&out->lock);
2426 stop_compressed_output_l(out);
2427 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002428 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429 return 0;
2430 }
2431 return -ENOSYS;
2432}
2433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434/** audio_stream_in implementation **/
2435static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2436{
2437 struct stream_in *in = (struct stream_in *)stream;
2438
2439 return in->config.rate;
2440}
2441
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002442static int in_set_sample_rate(struct audio_stream *stream __unused,
2443 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444{
2445 return -ENOSYS;
2446}
2447
2448static size_t in_get_buffer_size(const struct audio_stream *stream)
2449{
2450 struct stream_in *in = (struct stream_in *)stream;
2451
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002452 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2453 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002454 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2455 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002456
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002457 return in->config.period_size *
2458 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459}
2460
2461static uint32_t in_get_channels(const struct audio_stream *stream)
2462{
2463 struct stream_in *in = (struct stream_in *)stream;
2464
2465 return in->channel_mask;
2466}
2467
2468static audio_format_t in_get_format(const struct audio_stream *stream)
2469{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470 struct stream_in *in = (struct stream_in *)stream;
2471
2472 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473}
2474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002475static int in_set_format(struct audio_stream *stream __unused,
2476 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477{
2478 return -ENOSYS;
2479}
2480
2481static int in_standby(struct audio_stream *stream)
2482{
2483 struct stream_in *in = (struct stream_in *)stream;
2484 struct audio_device *adev = in->dev;
2485 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302486 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2487 stream, in->usecase, use_case_table[in->usecase]);
2488
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002489 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2490 /* Ignore standby in case of voip call because the voip input
2491 * stream is closed in adev_close_input_stream()
2492 */
2493 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2494 return status;
2495 }
2496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002498 if (!in->standby && in->is_st_session) {
2499 ALOGD("%s: sound trigger pcm stop lab", __func__);
2500 audio_extn_sound_trigger_stop_lab(in);
2501 in->standby = 1;
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002505 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002507 if (in->pcm) {
2508 pcm_close(in->pcm);
2509 in->pcm = NULL;
2510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002512 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 }
2514 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002515 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 return status;
2517}
2518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002519static int in_dump(const struct audio_stream *stream __unused,
2520 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521{
2522 return 0;
2523}
2524
2525static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2526{
2527 struct stream_in *in = (struct stream_in *)stream;
2528 struct audio_device *adev = in->dev;
2529 struct str_parms *parms;
2530 char *str;
2531 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002532 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302534 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 parms = str_parms_create_str(kvpairs);
2536
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302537 if (!parms)
2538 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002541
2542 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2543 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 val = atoi(value);
2545 /* no audio source uses val == 0 */
2546 if ((in->source != val) && (val != 0)) {
2547 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002548 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2549 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2550 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2551 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002552 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002553 err = voice_extn_compress_voip_open_input_stream(in);
2554 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002555 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002556 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002557 }
2558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 }
2560 }
2561
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002562 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2563 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002565 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 in->device = val;
2567 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002568 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 }
2571 }
2572
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002573done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002575 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
2577 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302578error:
Eric Laurent994a6932013-07-17 11:51:42 -07002579 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 return ret;
2581}
2582
2583static char* in_get_parameters(const struct audio_stream *stream,
2584 const char *keys)
2585{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002586 struct stream_in *in = (struct stream_in *)stream;
2587 struct str_parms *query = str_parms_create_str(keys);
2588 char *str;
2589 char value[256];
2590 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002591
2592 if (!query || !reply) {
2593 ALOGE("in_get_parameters: failed to create query or reply");
2594 return NULL;
2595 }
2596
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002597 ALOGV("%s: enter: keys - %s", __func__, keys);
2598
2599 voice_extn_in_get_parameters(in, query, reply);
2600
2601 str = str_parms_to_str(reply);
2602 str_parms_destroy(query);
2603 str_parms_destroy(reply);
2604
2605 ALOGV("%s: exit: returns - %s", __func__, str);
2606 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607}
2608
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002609static int in_set_gain(struct audio_stream_in *stream __unused,
2610 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611{
2612 return 0;
2613}
2614
2615static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2616 size_t bytes)
2617{
2618 struct stream_in *in = (struct stream_in *)stream;
2619 struct audio_device *adev = in->dev;
2620 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302621 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002625 if (in->is_st_session) {
2626 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2627 /* Read from sound trigger HAL */
2628 audio_extn_sound_trigger_read(in, buffer, bytes);
2629 pthread_mutex_unlock(&in->lock);
2630 return bytes;
2631 }
2632
2633 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2634 ALOGD(" %s: sound card is not active/SSR state", __func__);
2635 ret= -EIO;;
2636 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302637 }
2638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002640 pthread_mutex_lock(&adev->lock);
2641 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2642 ret = voice_extn_compress_voip_start_input_stream(in);
2643 else
2644 ret = start_input_stream(in);
2645 pthread_mutex_unlock(&adev->lock);
2646 if (ret != 0) {
2647 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 }
2649 in->standby = 0;
2650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651
2652 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002653 if (audio_extn_ssr_get_enabled() &&
2654 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002655 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002656 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2657 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002658 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2659 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002660 else
2661 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302662 if (ret < 0)
2663 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 }
2665
2666 /*
2667 * Instead of writing zeroes here, we could trust the hardware
2668 * to always provide zeroes when muted.
2669 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302670 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2671 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 memset(buffer, 0, bytes);
2673
2674exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302675 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302676 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002677 if (-ENETRESET == ret)
2678 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 pthread_mutex_unlock(&in->lock);
2681
2682 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302683 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302684 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302685 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302686 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302687 in->standby = true;
2688 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302689 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002691 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002692 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302693 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
2695 return bytes;
2696}
2697
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002698static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699{
2700 return 0;
2701}
2702
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002703static int add_remove_audio_effect(const struct audio_stream *stream,
2704 effect_handle_t effect,
2705 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002707 struct stream_in *in = (struct stream_in *)stream;
2708 int status = 0;
2709 effect_descriptor_t desc;
2710
2711 status = (*effect)->get_descriptor(effect, &desc);
2712 if (status != 0)
2713 return status;
2714
2715 pthread_mutex_lock(&in->lock);
2716 pthread_mutex_lock(&in->dev->lock);
2717 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2718 in->enable_aec != enable &&
2719 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2720 in->enable_aec = enable;
2721 if (!in->standby)
2722 select_devices(in->dev, in->usecase);
2723 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002724 if (in->enable_ns != enable &&
2725 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2726 in->enable_ns = enable;
2727 if (!in->standby)
2728 select_devices(in->dev, in->usecase);
2729 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002730 pthread_mutex_unlock(&in->dev->lock);
2731 pthread_mutex_unlock(&in->lock);
2732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 return 0;
2734}
2735
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002736static int in_add_audio_effect(const struct audio_stream *stream,
2737 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738{
Eric Laurent994a6932013-07-17 11:51:42 -07002739 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002740 return add_remove_audio_effect(stream, effect, true);
2741}
2742
2743static int in_remove_audio_effect(const struct audio_stream *stream,
2744 effect_handle_t effect)
2745{
Eric Laurent994a6932013-07-17 11:51:42 -07002746 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002747 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748}
2749
2750static int adev_open_output_stream(struct audio_hw_device *dev,
2751 audio_io_handle_t handle,
2752 audio_devices_t devices,
2753 audio_output_flags_t flags,
2754 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002755 struct audio_stream_out **stream_out,
2756 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757{
2758 struct audio_device *adev = (struct audio_device *)dev;
2759 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002760 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002761 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302764
2765 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2766 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2767 ALOGE(" sound card is not active rejecting compress output open request");
2768 return -EINVAL;
2769 }
2770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2772
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302773 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2774 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2775 devices, flags, &out->stream);
2776
2777
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002778 if (!out) {
2779 return -ENOMEM;
2780 }
2781
Haynes Mathew George204045b2015-02-25 20:32:03 -08002782 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2783 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 if (devices == AUDIO_DEVICE_NONE)
2786 devices = AUDIO_DEVICE_OUT_SPEAKER;
2787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 out->flags = flags;
2789 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002790 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002791 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002792 out->sample_rate = config->sample_rate;
2793 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2794 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002795 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002796 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002797 out->non_blocking = 0;
2798 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302800 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2801 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002802 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2803 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2804
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002805 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002806 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2807 ret = read_hdmi_channel_masks(out);
2808
2809 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2810 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002811 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002812 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002813 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002814
2815 if (config->sample_rate == 0)
2816 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2817 if (config->channel_mask == 0)
2818 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2819
2820 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2823 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002825 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002827 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2828 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002829 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002830 ret = voice_extn_compress_voip_open_output_stream(out);
2831 if (ret != 0) {
2832 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2833 __func__, ret);
2834 goto error_open;
2835 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2837 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2838 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2839 ALOGE("%s: Unsupported Offload information", __func__);
2840 ret = -EINVAL;
2841 goto error_open;
2842 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002843
2844 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2845 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2846 ALOGV("read and update_pass through formats");
2847 ret = audio_extn_dolby_update_passt_formats(adev, out);
2848 if(ret != 0) {
2849 goto error_open;
2850 }
2851 if(config->offload_info.format == 0)
2852 config->offload_info.format = out->supported_formats[0];
2853 }
2854
Mingming Yin90310102013-11-13 16:57:00 -08002855 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002856 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 ALOGE("%s: Unsupported audio format", __func__);
2858 ret = -EINVAL;
2859 goto error_open;
2860 }
2861
2862 out->compr_config.codec = (struct snd_codec *)
2863 calloc(1, sizeof(struct snd_codec));
2864
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002865 if (!out->compr_config.codec) {
2866 ret = -ENOMEM;
2867 goto error_open;
2868 }
2869
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002870 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 if (config->offload_info.channel_mask)
2872 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002873 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002875 config->offload_info.channel_mask = config->channel_mask;
2876 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002877 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 out->sample_rate = config->offload_info.sample_rate;
2879
2880 out->stream.set_callback = out_set_callback;
2881 out->stream.pause = out_pause;
2882 out->stream.resume = out_resume;
2883 out->stream.drain = out_drain;
2884 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002885 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002887 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002888 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002889 audio_extn_dolby_get_snd_codec_id(adev, out,
2890 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002891 else
2892 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302894 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002895 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002896 platform_get_pcm_offload_buffer_size(&config->offload_info);
2897 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2898 out->compr_config.fragment_size =
2899 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002900 } else {
2901 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002903 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2905 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002906 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 out->compr_config.codec->bit_rate =
2908 config->offload_info.bit_rate;
2909 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002910 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302912 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 /*TODO: Do we need to change it for passthrough */
2914 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915
Mingming Yin3ee55c62014-08-04 14:23:35 -07002916 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2917 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002918 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2919 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002920 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002921 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2922
Mingming Yin3ee55c62014-08-04 14:23:35 -07002923 if (out->bit_width == 24) {
2924 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2925 }
2926
Amit Shekhar6f461b12014-08-01 14:52:58 -07002927 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302928 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2931 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002932
Sharad Sangleb27354b2015-06-18 15:58:55 +05302933 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002934 //this flag is set from framework only if its for PCM formats
2935 //no need to check for PCM format again
2936 out->non_blocking = 0;
2937 out->use_small_bufs = true;
2938 ALOGI("Keep write blocking for small buff: non_blockling %d",
2939 out->non_blocking);
2940 }
2941
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002942 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002943 out->offload_state = OFFLOAD_STATE_IDLE;
2944 out->playback_started = 0;
2945
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002946 audio_extn_dts_create_state_notifier_node(out->usecase);
2947
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 create_offload_callback_thread(out);
2949 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2950 __func__, config->offload_info.version,
2951 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002952 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002953 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002954 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2955 ret = voice_check_and_set_incall_music_usecase(adev, out);
2956 if (ret != 0) {
2957 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2958 __func__, ret);
2959 goto error_open;
2960 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002961 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2962 if (config->sample_rate == 0)
2963 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2964 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2965 config->sample_rate != 8000) {
2966 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2967 ret = -EINVAL;
2968 goto error_open;
2969 }
2970 out->sample_rate = config->sample_rate;
2971 out->config.rate = config->sample_rate;
2972 if (config->format == AUDIO_FORMAT_DEFAULT)
2973 config->format = AUDIO_FORMAT_PCM_16_BIT;
2974 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2975 config->format = AUDIO_FORMAT_PCM_16_BIT;
2976 ret = -EINVAL;
2977 goto error_open;
2978 }
2979 out->format = config->format;
2980 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2981 out->config = pcm_config_afe_proxy_playback;
2982 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002983 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002984 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2986 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002987 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002988 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2989 format = AUDIO_FORMAT_PCM_16_BIT;
2990 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2991 out->config = pcm_config_deep_buffer;
2992 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002993 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002994 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002995 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002996 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002997 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002998 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 }
3000
Amit Shekhar1d896042014-10-03 13:16:09 -07003001 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3002 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003003 /* TODO remove this hardcoding and check why width is zero*/
3004 if (out->bit_width == 0)
3005 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003006 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3007 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003008 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303009 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003010 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3011 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3012 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003013 if(adev->primary_output == NULL)
3014 adev->primary_output = out;
3015 else {
3016 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003017 ret = -EEXIST;
3018 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003019 }
3020 }
3021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 /* Check if this usecase is already existing */
3023 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003024 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3025 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003028 ret = -EEXIST;
3029 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 }
3031 pthread_mutex_unlock(&adev->lock);
3032
3033 out->stream.common.get_sample_rate = out_get_sample_rate;
3034 out->stream.common.set_sample_rate = out_set_sample_rate;
3035 out->stream.common.get_buffer_size = out_get_buffer_size;
3036 out->stream.common.get_channels = out_get_channels;
3037 out->stream.common.get_format = out_get_format;
3038 out->stream.common.set_format = out_set_format;
3039 out->stream.common.standby = out_standby;
3040 out->stream.common.dump = out_dump;
3041 out->stream.common.set_parameters = out_set_parameters;
3042 out->stream.common.get_parameters = out_get_parameters;
3043 out->stream.common.add_audio_effect = out_add_audio_effect;
3044 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3045 out->stream.get_latency = out_get_latency;
3046 out->stream.set_volume = out_set_volume;
3047 out->stream.write = out_write;
3048 out->stream.get_render_position = out_get_render_position;
3049 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003053 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003054 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055
3056 config->format = out->stream.common.get_format(&out->stream.common);
3057 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3058 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3059
3060 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303061 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3062 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003063
3064 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3065 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3066 popcount(out->channel_mask), out->playback_started);
3067
Eric Laurent994a6932013-07-17 11:51:42 -07003068 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003070
3071error_open:
3072 free(out);
3073 *stream_out = NULL;
3074 ALOGD("%s: exit: ret %d", __func__, ret);
3075 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076}
3077
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003078static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 struct audio_stream_out *stream)
3080{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 struct stream_out *out = (struct stream_out *)stream;
3082 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303085 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3086
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303088 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003089 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303090 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003091 if(ret != 0)
3092 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3093 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003094 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 out_standby(&stream->common);
3096
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003097 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003098 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003100 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003101 if (out->compr_config.codec != NULL)
3102 free(out->compr_config.codec);
3103 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003104
3105 if (adev->voice_tx_output == out)
3106 adev->voice_tx_output = NULL;
3107
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108 pthread_cond_destroy(&out->cond);
3109 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003111 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112}
3113
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003114static void close_compress_sessions(struct audio_device *adev)
3115{
Mingming Yin7b762e72015-03-04 13:47:32 -08003116 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303117 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003118 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003119 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303120
3121 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003122 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303123 if (is_offload_usecase(usecase->id)) {
3124 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003125 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3126 out = usecase->stream.out;
3127 pthread_mutex_unlock(&adev->lock);
3128 out_standby(&out->stream.common);
3129 pthread_mutex_lock(&adev->lock);
3130 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303131 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003132 }
3133 pthread_mutex_unlock(&adev->lock);
3134}
3135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3137{
3138 struct audio_device *adev = (struct audio_device *)dev;
3139 struct str_parms *parms;
3140 char *str;
3141 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003142 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 int ret;
3144 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003146 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303149 if (!parms)
3150 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003151 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3152 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303153 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303154 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303155 struct listnode *node;
3156 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303157 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303158 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003159 //close compress sessions on OFFLINE status
3160 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 } else if (strstr(snd_card_status, "ONLINE")) {
3162 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303163 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303164 if (!platform_is_acdb_initialized(adev->platform)) {
3165 ret = platform_acdb_init(adev->platform);
3166 if(ret)
3167 ALOGE("acdb initialization is failed");
3168
3169 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 }
3172
3173 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003174 status = voice_set_parameters(adev, parms);
3175 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003176 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 status = platform_set_parameters(adev->platform, parms);
3179 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003180 goto done;
3181
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3183 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003184 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3186 adev->bluetooth_nrec = true;
3187 else
3188 adev->bluetooth_nrec = false;
3189 }
3190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003191 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3192 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3194 adev->screen_off = false;
3195 else
3196 adev->screen_off = true;
3197 }
3198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003199 ret = str_parms_get_int(parms, "rotation", &val);
3200 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003201 bool reverse_speakers = false;
3202 switch(val) {
3203 // FIXME: note that the code below assumes that the speakers are in the correct placement
3204 // relative to the user when the device is rotated 90deg from its default rotation. This
3205 // assumption is device-specific, not platform-specific like this code.
3206 case 270:
3207 reverse_speakers = true;
3208 break;
3209 case 0:
3210 case 90:
3211 case 180:
3212 break;
3213 default:
3214 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003215 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003216 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003217 if (status == 0) {
3218 if (adev->speaker_lr_swap != reverse_speakers) {
3219 adev->speaker_lr_swap = reverse_speakers;
3220 // only update the selected device if there is active pcm playback
3221 struct audio_usecase *usecase;
3222 struct listnode *node;
3223 list_for_each(node, &adev->usecase_list) {
3224 usecase = node_to_item(node, struct audio_usecase, list);
3225 if (usecase->type == PCM_PLAYBACK) {
3226 select_devices(adev, usecase->id);
3227 break;
3228 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 }
3230 }
3231 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003232 }
3233
Mingming Yin514a8bc2014-07-29 15:22:21 -07003234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3235 if (ret >= 0) {
3236 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3237 adev->bt_wb_speech_enabled = true;
3238 else
3239 adev->bt_wb_speech_enabled = false;
3240 }
3241
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3243 if (ret >= 0) {
3244 val = atoi(value);
3245 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3246 ALOGV("cache new edid");
3247 platform_cache_edid(adev->platform);
3248 }
3249 }
3250
3251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3252 if (ret >= 0) {
3253 val = atoi(value);
3254 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3255 ALOGV("invalidate cached edid");
3256 platform_invalidate_edid(adev->platform);
3257 }
3258 }
3259
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003260 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003261
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003262done:
3263 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003264 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303265error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003266 ALOGV("%s: exit with code(%d)", __func__, status);
3267 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
3270static char* adev_get_parameters(const struct audio_hw_device *dev,
3271 const char *keys)
3272{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003273 struct audio_device *adev = (struct audio_device *)dev;
3274 struct str_parms *reply = str_parms_create();
3275 struct str_parms *query = str_parms_create_str(keys);
3276 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303277 char value[256] = {0};
3278 int ret = 0;
3279
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003280 if (!query || !reply) {
3281 ALOGE("adev_get_parameters: failed to create query or reply");
3282 return NULL;
3283 }
3284
Naresh Tannirud7205b62014-06-20 02:54:48 +05303285 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3286 sizeof(value));
3287 if (ret >=0) {
3288 int val = 1;
3289 pthread_mutex_lock(&adev->snd_card_status.lock);
3290 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3291 val = 0;
3292 pthread_mutex_unlock(&adev->snd_card_status.lock);
3293 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3294 goto exit;
3295 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003296
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003297 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003298 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003299 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003300 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303301 pthread_mutex_unlock(&adev->lock);
3302
Naresh Tannirud7205b62014-06-20 02:54:48 +05303303exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003304 str = str_parms_to_str(reply);
3305 str_parms_destroy(query);
3306 str_parms_destroy(reply);
3307
3308 ALOGV("%s: exit: returns - %s", __func__, str);
3309 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310}
3311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003312static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return 0;
3315}
3316
3317static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3318{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003319 int ret;
3320 struct audio_device *adev = (struct audio_device *)dev;
3321 pthread_mutex_lock(&adev->lock);
3322 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003323 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003324 pthread_mutex_unlock(&adev->lock);
3325 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326}
3327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003328static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3329 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330{
3331 return -ENOSYS;
3332}
3333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003334static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3335 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 return -ENOSYS;
3338}
3339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3341 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342{
3343 return -ENOSYS;
3344}
3345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003346static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3347 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348{
3349 return -ENOSYS;
3350}
3351
3352static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3353{
3354 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 pthread_mutex_lock(&adev->lock);
3357 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003360 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3361 voice_is_in_call(adev)) {
3362 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303363 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003364 adev->current_call_output = NULL;
3365 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 }
3367 pthread_mutex_unlock(&adev->lock);
3368 return 0;
3369}
3370
3371static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3372{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003373 int ret;
3374
3375 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003376 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003377 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3378 pthread_mutex_unlock(&adev->lock);
3379
3380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
3383static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3384{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003385 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 return 0;
3387}
3388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 const struct audio_config *config)
3391{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003392 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003394 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3395 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
3398static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003399 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 audio_devices_t devices,
3401 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003402 struct audio_stream_in **stream_in,
3403 audio_input_flags_t flags __unused,
3404 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003405 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406{
3407 struct audio_device *adev = (struct audio_device *)dev;
3408 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003409 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003410 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003411 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 *stream_in = NULL;
3414 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3415 return -EINVAL;
3416
3417 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003418
3419 if (!in) {
3420 ALOGE("failed to allocate input stream");
3421 return -ENOMEM;
3422 }
3423
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303424 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003425 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3426 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003428 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 in->stream.common.get_sample_rate = in_get_sample_rate;
3431 in->stream.common.set_sample_rate = in_set_sample_rate;
3432 in->stream.common.get_buffer_size = in_get_buffer_size;
3433 in->stream.common.get_channels = in_get_channels;
3434 in->stream.common.get_format = in_get_format;
3435 in->stream.common.set_format = in_set_format;
3436 in->stream.common.standby = in_standby;
3437 in->stream.common.dump = in_dump;
3438 in->stream.common.set_parameters = in_set_parameters;
3439 in->stream.common.get_parameters = in_get_parameters;
3440 in->stream.common.add_audio_effect = in_add_audio_effect;
3441 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3442 in->stream.set_gain = in_set_gain;
3443 in->stream.read = in_read;
3444 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3445
3446 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003447 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 in->standby = 1;
3450 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003451 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452
3453 /* Update config params with the requested sample rate and channels */
3454 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003455 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3456 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3457 is_low_latency = true;
3458#if LOW_LATENCY_CAPTURE_USE_CASE
3459 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3460#endif
3461 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003464 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003466 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303467 if (adev->mode != AUDIO_MODE_IN_CALL) {
3468 ret = -EINVAL;
3469 goto err_open;
3470 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003471 if (config->sample_rate == 0)
3472 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3473 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3474 config->sample_rate != 8000) {
3475 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3476 ret = -EINVAL;
3477 goto err_open;
3478 }
3479 if (config->format == AUDIO_FORMAT_DEFAULT)
3480 config->format = AUDIO_FORMAT_PCM_16_BIT;
3481 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3482 config->format = AUDIO_FORMAT_PCM_16_BIT;
3483 ret = -EINVAL;
3484 goto err_open;
3485 }
3486
3487 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3488 in->config = pcm_config_afe_proxy_record;
3489 in->config.channels = channel_count;
3490 in->config.rate = config->sample_rate;
3491 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003492 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003493 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003494 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3495 ret = -EINVAL;
3496 goto err_open;
3497 }
3498 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003499 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003500 }
Mingming Yine62d7842013-10-25 16:26:03 -07003501 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003502 audio_extn_compr_cap_format_supported(config->format) &&
3503 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003504 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003505 } else {
3506 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003507 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 buffer_size = get_input_buffer_size(config->sample_rate,
3509 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003510 channel_count,
3511 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003512 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003513 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3514 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3515 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3516 (in->config.rate == 8000 || in->config.rate == 16000) &&
3517 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3518 voice_extn_compress_voip_open_input_stream(in);
3519 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003522 /* This stream could be for sound trigger lab,
3523 get sound trigger pcm if present */
3524 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303525 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003528 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003529 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
3531err_open:
3532 free(in);
3533 *stream_in = NULL;
3534 return ret;
3535}
3536
3537static void adev_close_input_stream(struct audio_hw_device *dev,
3538 struct audio_stream_in *stream)
3539{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003541 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003542 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303543
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303544 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003545
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303546 /* Disable echo reference while closing input stream */
3547 platform_set_echo_reference(adev->platform, false);
3548
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303550 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003551 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303552 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003553 if (ret != 0)
3554 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3555 __func__, ret);
3556 } else
3557 in_standby(&stream->common);
3558
Mingming Yin7b762e72015-03-04 13:47:32 -08003559 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003560 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003561 audio_extn_ssr_deinit();
3562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563
Mingming Yine62d7842013-10-25 16:26:03 -07003564 if(audio_extn_compr_cap_enabled() &&
3565 audio_extn_compr_cap_format_supported(in->config.format))
3566 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003567
3568 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 return;
3570}
3571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003572static int adev_dump(const audio_hw_device_t *device __unused,
3573 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574{
3575 return 0;
3576}
3577
3578static int adev_close(hw_device_t *device)
3579{
3580 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003581
3582 if (!adev)
3583 return 0;
3584
3585 pthread_mutex_lock(&adev_init_lock);
3586
3587 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003588 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003589 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003590 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003591 audio_route_free(adev->audio_route);
3592 free(adev->snd_dev_ref_cnt);
3593 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003594 free(device);
3595 adev = NULL;
3596 }
3597 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 return 0;
3599}
3600
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003601/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3602 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3603 * just that it _might_ work.
3604 */
3605static int period_size_is_plausible_for_low_latency(int period_size)
3606{
3607 switch (period_size) {
3608 case 160:
3609 case 240:
3610 case 320:
3611 case 480:
3612 return 1;
3613 default:
3614 return 0;
3615 }
3616}
3617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618static int adev_open(const hw_module_t *module, const char *name,
3619 hw_device_t **device)
3620{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003621 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003623 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3625
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003626 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003627 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003628 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003629 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003630 ALOGD("%s: returning existing instance of adev", __func__);
3631 ALOGD("%s: exit", __func__);
3632 pthread_mutex_unlock(&adev_init_lock);
3633 return 0;
3634 }
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev = calloc(1, sizeof(struct audio_device));
3637
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003638 if (!adev) {
3639 pthread_mutex_unlock(&adev_init_lock);
3640 return -ENOMEM;
3641 }
3642
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003643 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3646 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3647 adev->device.common.module = (struct hw_module_t *)module;
3648 adev->device.common.close = adev_close;
3649
3650 adev->device.init_check = adev_init_check;
3651 adev->device.set_voice_volume = adev_set_voice_volume;
3652 adev->device.set_master_volume = adev_set_master_volume;
3653 adev->device.get_master_volume = adev_get_master_volume;
3654 adev->device.set_master_mute = adev_set_master_mute;
3655 adev->device.get_master_mute = adev_get_master_mute;
3656 adev->device.set_mode = adev_set_mode;
3657 adev->device.set_mic_mute = adev_set_mic_mute;
3658 adev->device.get_mic_mute = adev_get_mic_mute;
3659 adev->device.set_parameters = adev_set_parameters;
3660 adev->device.get_parameters = adev_get_parameters;
3661 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3662 adev->device.open_output_stream = adev_open_output_stream;
3663 adev->device.close_output_stream = adev_close_output_stream;
3664 adev->device.open_input_stream = adev_open_input_stream;
3665 adev->device.close_input_stream = adev_close_input_stream;
3666 adev->device.dump = adev_dump;
3667
3668 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003670 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003671 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003674 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003675 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003676 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003677 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003678 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003679 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003680 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303681 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303682
3683 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3684 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003686 adev->platform = platform_init(adev);
3687 if (!adev->platform) {
3688 free(adev->snd_dev_ref_cnt);
3689 free(adev);
3690 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3691 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003692 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003693 return -EINVAL;
3694 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003695
Naresh Tanniru4c630392014-05-12 01:05:52 +05303696 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3697
Eric Laurentc4aef752013-09-12 17:45:53 -07003698 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3699 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3700 if (adev->visualizer_lib == NULL) {
3701 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3702 } else {
3703 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3704 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003705 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003706 "visualizer_hal_start_output");
3707 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003708 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003709 "visualizer_hal_stop_output");
3710 }
3711 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003712 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003713 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003714
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003715 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3716 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3717 if (adev->offload_effects_lib == NULL) {
3718 ALOGE("%s: DLOPEN failed for %s", __func__,
3719 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3720 } else {
3721 ALOGV("%s: DLOPEN successful for %s", __func__,
3722 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3723 adev->offload_effects_start_output =
3724 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3725 "offload_effects_bundle_hal_start_output");
3726 adev->offload_effects_stop_output =
3727 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3728 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003729 adev->offload_effects_set_hpx_state =
3730 (int (*)(bool))dlsym(adev->offload_effects_lib,
3731 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003732 }
3733 }
3734
Mingming Yin514a8bc2014-07-29 15:22:21 -07003735 adev->bt_wb_speech_enabled = false;
3736
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003737 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 *device = &adev->device.common;
3739
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003740 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3741 &adev->streams_output_cfg_list);
3742
Kiran Kandi910e1862013-10-29 13:29:42 -07003743 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003744
3745 char value[PROPERTY_VALUE_MAX];
3746 int trial;
3747 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3748 trial = atoi(value);
3749 if (period_size_is_plausible_for_low_latency(trial)) {
3750 pcm_config_low_latency.period_size = trial;
3751 pcm_config_low_latency.start_threshold = trial / 4;
3752 pcm_config_low_latency.avail_min = trial / 4;
3753 configured_low_latency_capture_period_size = trial;
3754 }
3755 }
3756 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3757 trial = atoi(value);
3758 if (period_size_is_plausible_for_low_latency(trial)) {
3759 configured_low_latency_capture_period_size = trial;
3760 }
3761 }
3762
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003763 pthread_mutex_unlock(&adev_init_lock);
3764
Eric Laurent994a6932013-07-17 11:51:42 -07003765 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 return 0;
3767}
3768
3769static struct hw_module_methods_t hal_module_methods = {
3770 .open = adev_open,
3771};
3772
3773struct audio_module HAL_MODULE_INFO_SYM = {
3774 .common = {
3775 .tag = HARDWARE_MODULE_TAG,
3776 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3777 .hal_api_version = HARDWARE_HAL_API_VERSION,
3778 .id = AUDIO_HARDWARE_MODULE_ID,
3779 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003780 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 .methods = &hal_module_methods,
3782 },
3783};