blob: 6843a64f84ef694ac7b3f3918b6d6c1c98388995 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800489 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200567 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568 audio_extn_sound_trigger_update_device_status(snd_device,
569 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530570 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800571 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 return 0;
575}
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577static void check_usecases_codec_backend(struct audio_device *adev,
578 struct audio_usecase *uc_info,
579 snd_device_t snd_device)
580{
581 struct listnode *node;
582 struct audio_usecase *usecase;
583 bool switch_device[AUDIO_USECASE_MAX];
584 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530585 int backend_idx = DEFAULT_CODEC_BACKEND;
586 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587
588 /*
589 * This function is to make sure that all the usecases that are active on
590 * the hardware codec backend are always routed to any one device that is
591 * handled by the hardware codec.
592 * For example, if low-latency and deep-buffer usecases are currently active
593 * on speaker and out_set_parameters(headset) is received on low-latency
594 * output, then we have to make sure deep-buffer is also switched to headset,
595 * because of the limitation that both the devices cannot be enabled
596 * at the same time as they share the same backend.
597 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700598 /*
599 * This call is to check if we need to force routing for a particular stream
600 * If there is a backend configuration change for the device when a
601 * new stream starts, then ADM needs to be closed and re-opened with the new
602 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530603 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700604 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530605 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
606 snd_device);
607 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800609 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800610 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 for (i = 0; i < AUDIO_USECASE_MAX; i++)
612 switch_device[i] = false;
613
614 list_for_each(node, &adev->usecase_list) {
615 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530616
617 if (usecase == uc_info)
618 continue;
619 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
620 ALOGV("%s: backend_idx: %d,"
621 "usecase_backend_idx: %d, curr device: %s, usecase device:"
622 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
623 platform_get_snd_device_name(usecase->out_snd_device));
624
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800625 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700626 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530627 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
628 usecase_backend_idx == backend_idx) {
629 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
630 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700631 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700632 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 switch_device[usecase->id] = true;
634 num_uc_to_switch++;
635 }
636 }
637
638 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700639 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530641 /* Make sure the previous devices to be disabled first and then enable the
642 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
645 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700646 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 }
648 }
649
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700650 list_for_each(node, &adev->usecase_list) {
651 usecase = node_to_item(node, struct audio_usecase, list);
652 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700653 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700654 }
655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 /* Re-route all the usecases on the shared backend other than the
658 specified usecase to new snd devices */
659 list_for_each(node, &adev->usecase_list) {
660 usecase = node_to_item(node, struct audio_usecase, list);
661 /* Update the out_snd_device only before enabling the audio route */
662 if (switch_device[usecase->id] ) {
663 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800664 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530665 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 }
667 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
669}
670
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700671static void check_and_route_capture_usecases(struct audio_device *adev,
672 struct audio_usecase *uc_info,
673 snd_device_t snd_device)
674{
675 struct listnode *node;
676 struct audio_usecase *usecase;
677 bool switch_device[AUDIO_USECASE_MAX];
678 int i, num_uc_to_switch = 0;
679
680 /*
681 * This function is to make sure that all the active capture usecases
682 * are always routed to the same input sound device.
683 * For example, if audio-record and voice-call usecases are currently
684 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
685 * is received for voice call then we have to make sure that audio-record
686 * usecase is also switched to earpiece i.e. voice-dmic-ef,
687 * because of the limitation that two devices cannot be enabled
688 * at the same time if they share the same backend.
689 */
690 for (i = 0; i < AUDIO_USECASE_MAX; i++)
691 switch_device[i] = false;
692
693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800695 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700696 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700697 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530698 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700699 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
701 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700702 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700703 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 switch_device[usecase->id] = true;
705 num_uc_to_switch++;
706 }
707 }
708
709 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700710 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530712 /* Make sure the previous devices to be disabled first and then enable the
713 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800718 }
719 }
720
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700724 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700725 }
726 }
727
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 /* Re-route all the usecases on the shared backend other than the
729 specified usecase to new snd devices */
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 /* Update the in_snd_device only before enabling the audio route */
733 if (switch_device[usecase->id] ) {
734 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800735 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530736 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 }
738 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 }
740}
741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800742/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700743static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700745 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700746 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747
748 switch (channels) {
749 /*
750 * Do not handle stereo output in Multi-channel cases
751 * Stereo case is handled in normal playback path
752 */
753 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700754 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
759 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 break;
761 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __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;
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769 break;
770 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700771 ALOGE("HDMI does not support multi channel playback");
772 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 break;
774 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776}
777
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800778audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
779 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700780{
781 struct audio_usecase *usecase;
782 struct listnode *node;
783
784 list_for_each(node, &adev->usecase_list) {
785 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800786 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700787 ALOGV("%s: usecase id %d", __func__, usecase->id);
788 return usecase->id;
789 }
790 }
791 return USECASE_INVALID;
792}
793
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700794struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700796{
797 struct audio_usecase *usecase;
798 struct listnode *node;
799
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
802 if (usecase->id == uc_id)
803 return usecase;
804 }
805 return NULL;
806}
807
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700808int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800810 snd_device_t out_snd_device = SND_DEVICE_NONE;
811 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 struct audio_usecase *usecase = NULL;
813 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800814 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800815 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800816 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800817 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 usecase = get_usecase_from_list(adev, uc_id);
821 if (usecase == NULL) {
822 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
823 return -EINVAL;
824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800826 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800827 (usecase->type == VOIP_CALL) ||
828 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700829 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800830 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700831 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 usecase->devices = usecase->stream.out->devices;
833 } else {
834 /*
835 * If the voice call is active, use the sound devices of voice call usecase
836 * so that it would not result any device switch. All the usecases will
837 * be switched to new device when select_devices() is called for voice call
838 * usecase. This is to avoid switching devices for voice call when
839 * check_usecases_codec_backend() is called below.
840 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700841 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800843 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700844 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
845 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 in_snd_device = vc_usecase->in_snd_device;
847 out_snd_device = vc_usecase->out_snd_device;
848 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 } else if (voice_extn_compress_voip_is_active(adev)) {
850 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700851 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530852 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700853 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 in_snd_device = voip_usecase->in_snd_device;
855 out_snd_device = voip_usecase->out_snd_device;
856 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800857 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800858 hfp_ucid = audio_extn_hfp_get_usecase();
859 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800861 in_snd_device = hfp_usecase->in_snd_device;
862 out_snd_device = hfp_usecase->out_snd_device;
863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 }
865 if (usecase->type == PCM_PLAYBACK) {
866 usecase->devices = usecase->stream.out->devices;
867 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800870 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700871 if (usecase->stream.out == adev->primary_output &&
872 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800873 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
874 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700875 select_devices(adev, adev->active_input->usecase);
876 }
877 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 } else if (usecase->type == PCM_CAPTURE) {
879 usecase->devices = usecase->stream.in->device;
880 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700882 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530883 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
884 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
885 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
886 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700887 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800888 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
890 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700892 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 }
895 }
896
897 if (out_snd_device == usecase->out_snd_device &&
898 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 return 0;
900 }
901
sangwoobc677242013-08-08 16:53:43 +0900902 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700903 out_snd_device, platform_get_snd_device_name(out_snd_device),
904 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906 /*
907 * Limitation: While in call, to do a device switch we need to disable
908 * and enable both RX and TX devices though one of them is same as current
909 * device.
910 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700911 if ((usecase->type == VOICE_CALL) &&
912 (usecase->in_snd_device != SND_DEVICE_NONE) &&
913 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700914 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /* Disable current sound devices */
918 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700919 disable_audio_route(adev, usecase);
920 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 }
922
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700924 disable_audio_route(adev, usecase);
925 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800926 }
927
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800928 /* Applicable only on the targets that has external modem.
929 * New device information should be sent to modem before enabling
930 * the devices to reduce in-call device switch time.
931 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700932 if ((usecase->type == VOICE_CALL) &&
933 (usecase->in_snd_device != SND_DEVICE_NONE) &&
934 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800935 status = platform_switch_voice_call_enable_device_config(adev->platform,
936 out_snd_device,
937 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700938 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 /* Enable new sound devices */
941 if (out_snd_device != SND_DEVICE_NONE) {
942 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
943 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700944 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945 }
946
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700947 if (in_snd_device != SND_DEVICE_NONE) {
948 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951
Avinash Vaish71a8b972014-07-24 15:36:33 +0530952 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700953 status = platform_switch_voice_call_device_post(adev->platform,
954 out_snd_device,
955 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530956 enable_audio_route_for_voice_usecases(adev, usecase);
957 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800958
sangwoo170731f2013-06-08 15:36:36 +0900959 usecase->in_snd_device = in_snd_device;
960 usecase->out_snd_device = out_snd_device;
961
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530962 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700963 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530964 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700965 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530966 usecase->stream.out->flags,
967 usecase->stream.out->format,
968 usecase->stream.out->sample_rate,
969 usecase->stream.out->bit_width,
Manish Dewanganf48adb42015-05-27 10:17:41 +0530970 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530971 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700972 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530973 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700974
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700975 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900976
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800977 /* Applicable only on the targets that has external modem.
978 * Enable device command should be sent to modem only after
979 * enabling voice call mixer controls
980 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700981 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800982 status = platform_switch_voice_call_usecase_route_post(adev->platform,
983 out_snd_device,
984 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530985 ALOGD("%s: done",__func__);
986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987 return status;
988}
989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990static int stop_input_stream(struct stream_in *in)
991{
992 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993 struct audio_usecase *uc_info;
994 struct audio_device *adev = in->dev;
995
Eric Laurentc8400632013-02-14 19:04:54 -0800996 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997
Eric Laurent994a6932013-07-17 11:51:42 -0700998 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 uc_info = get_usecase_from_list(adev, in->usecase);
1001 if (uc_info == NULL) {
1002 ALOGE("%s: Could not find the usecase (%d) in the list",
1003 __func__, in->usecase);
1004 return -EINVAL;
1005 }
1006
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001007 /* Close in-call recording streams */
1008 voice_check_and_stop_incall_rec_usecase(adev, in);
1009
Eric Laurent150dbfe2013-02-27 14:31:02 -08001010 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001011 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001012
1013 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001014 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001016 list_remove(&uc_info->list);
1017 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018
Eric Laurent994a6932013-07-17 11:51:42 -07001019 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 return ret;
1021}
1022
1023int start_input_stream(struct stream_in *in)
1024{
1025 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001026 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 struct audio_usecase *uc_info;
1028 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301029 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030
Mingming Yine62d7842013-10-25 16:26:03 -07001031 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301032 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1033 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001034
Naresh Tanniru80659832014-06-04 18:17:56 +05301035
1036 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301037 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301038 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301039 goto error_config;
1040 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301041
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001042 /* Check if source matches incall recording usecase criteria */
1043 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1044 if (ret)
1045 goto error_config;
1046 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001047 ALOGD("%s: Updated usecase(%d: %s)",
1048 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001049
Eric Laurentb23d5282013-05-14 15:27:20 -07001050 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051 if (in->pcm_device_id < 0) {
1052 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1053 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001054 ret = -EINVAL;
1055 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057
1058 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001060
1061 if (!uc_info) {
1062 ret = -ENOMEM;
1063 goto error_config;
1064 }
1065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 uc_info->id = in->usecase;
1067 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001068 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 uc_info->devices = in->device;
1070 uc_info->in_snd_device = SND_DEVICE_NONE;
1071 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001073 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301074 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001075 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076
Eric Laurentc8400632013-02-14 19:04:54 -08001077 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001078 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1079
1080 unsigned int flags = PCM_IN;
1081 unsigned int pcm_open_retry_count = 0;
1082
1083 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1084 flags |= PCM_MMAP | PCM_NOIRQ;
1085 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1086 }
1087
1088 while (1) {
1089 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1090 flags, &in->config);
1091 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1092 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1093 if (in->pcm != NULL) {
1094 pcm_close(in->pcm);
1095 in->pcm = NULL;
1096 }
1097 if (pcm_open_retry_count-- == 0) {
1098 ret = -EIO;
1099 goto error_open;
1100 }
1101 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1102 continue;
1103 }
1104 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301106 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301107
Eric Laurent994a6932013-07-17 11:51:42 -07001108 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001109 return ret;
1110
1111error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301113 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001114
1115error_config:
1116 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001118
1119 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120}
1121
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001122/* must be called with out->lock locked */
1123static int send_offload_cmd_l(struct stream_out* out, int command)
1124{
1125 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1126
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001127 if (!cmd) {
1128 ALOGE("failed to allocate mem for command 0x%x", command);
1129 return -ENOMEM;
1130 }
1131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001132 ALOGVV("%s %d", __func__, command);
1133
1134 cmd->cmd = command;
1135 list_add_tail(&out->offload_cmd_list, &cmd->node);
1136 pthread_cond_signal(&out->offload_cond);
1137 return 0;
1138}
1139
1140/* must be called iwth out->lock locked */
1141static void stop_compressed_output_l(struct stream_out *out)
1142{
1143 out->offload_state = OFFLOAD_STATE_IDLE;
1144 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001145 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001146 if (out->compr != NULL) {
1147 compress_stop(out->compr);
1148 while (out->offload_thread_blocked) {
1149 pthread_cond_wait(&out->cond, &out->lock);
1150 }
1151 }
1152}
1153
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001154bool is_offload_usecase(audio_usecase_t uc_id)
1155{
1156 unsigned int i;
1157 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1158 if (uc_id == offload_usecases[i])
1159 return true;
1160 }
1161 return false;
1162}
1163
1164static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1165{
1166 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1167 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1168 char value[PROPERTY_VALUE_MAX] = {0};
1169
1170 property_get("audio.offload.multiple.enabled", value, NULL);
1171 if (!(atoi(value) || !strncmp("true", value, 4)))
1172 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1173
1174 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1175 for (i = 0; i < num_usecase; i++) {
1176 if (!(adev->offload_usecases_state & (0x1<<i))) {
1177 adev->offload_usecases_state |= 0x1 << i;
1178 ret = offload_usecases[i];
1179 break;
1180 }
1181 }
1182 ALOGV("%s: offload usecase is %d", __func__, ret);
1183 return ret;
1184}
1185
1186static void free_offload_usecase(struct audio_device *adev,
1187 audio_usecase_t uc_id)
1188{
1189 unsigned int i;
1190 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1191 if (offload_usecases[i] == uc_id) {
1192 adev->offload_usecases_state &= ~(0x1<<i);
1193 break;
1194 }
1195 }
1196 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1197}
1198
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001199static void *offload_thread_loop(void *context)
1200{
1201 struct stream_out *out = (struct stream_out *) context;
1202 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001203 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001204
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001205 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1206 set_sched_policy(0, SP_FOREGROUND);
1207 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1208
1209 ALOGV("%s", __func__);
1210 pthread_mutex_lock(&out->lock);
1211 for (;;) {
1212 struct offload_cmd *cmd = NULL;
1213 stream_callback_event_t event;
1214 bool send_callback = false;
1215
1216 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1217 __func__, list_empty(&out->offload_cmd_list),
1218 out->offload_state);
1219 if (list_empty(&out->offload_cmd_list)) {
1220 ALOGV("%s SLEEPING", __func__);
1221 pthread_cond_wait(&out->offload_cond, &out->lock);
1222 ALOGV("%s RUNNING", __func__);
1223 continue;
1224 }
1225
1226 item = list_head(&out->offload_cmd_list);
1227 cmd = node_to_item(item, struct offload_cmd, node);
1228 list_remove(item);
1229
1230 ALOGVV("%s STATE %d CMD %d out->compr %p",
1231 __func__, out->offload_state, cmd->cmd, out->compr);
1232
1233 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1234 free(cmd);
1235 break;
1236 }
1237
1238 if (out->compr == NULL) {
1239 ALOGE("%s: Compress handle is NULL", __func__);
1240 pthread_cond_signal(&out->cond);
1241 continue;
1242 }
1243 out->offload_thread_blocked = true;
1244 pthread_mutex_unlock(&out->lock);
1245 send_callback = false;
1246 switch(cmd->cmd) {
1247 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001248 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001249 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001250 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001251 send_callback = true;
1252 event = STREAM_CBK_EVENT_WRITE_READY;
1253 break;
1254 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001255 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301256 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001257 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301258 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001259 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301260 if (ret < 0)
1261 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301262 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301263 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001264 compress_drain(out->compr);
1265 else
1266 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301267 if (ret != -ENETRESET) {
1268 send_callback = true;
1269 event = STREAM_CBK_EVENT_DRAIN_READY;
1270 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1271 } else
1272 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001273 break;
1274 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001275 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001277 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001278 send_callback = true;
1279 event = STREAM_CBK_EVENT_DRAIN_READY;
1280 break;
1281 default:
1282 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1283 break;
1284 }
1285 pthread_mutex_lock(&out->lock);
1286 out->offload_thread_blocked = false;
1287 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001288 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001289 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001291 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 free(cmd);
1293 }
1294
1295 pthread_cond_signal(&out->cond);
1296 while (!list_empty(&out->offload_cmd_list)) {
1297 item = list_head(&out->offload_cmd_list);
1298 list_remove(item);
1299 free(node_to_item(item, struct offload_cmd, node));
1300 }
1301 pthread_mutex_unlock(&out->lock);
1302
1303 return NULL;
1304}
1305
1306static int create_offload_callback_thread(struct stream_out *out)
1307{
1308 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1309 list_init(&out->offload_cmd_list);
1310 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1311 offload_thread_loop, out);
1312 return 0;
1313}
1314
1315static int destroy_offload_callback_thread(struct stream_out *out)
1316{
1317 pthread_mutex_lock(&out->lock);
1318 stop_compressed_output_l(out);
1319 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1320
1321 pthread_mutex_unlock(&out->lock);
1322 pthread_join(out->offload_thread, (void **) NULL);
1323 pthread_cond_destroy(&out->offload_cond);
1324
1325 return 0;
1326}
1327
Eric Laurent07eeafd2013-10-06 12:52:49 -07001328static bool allow_hdmi_channel_config(struct audio_device *adev)
1329{
1330 struct listnode *node;
1331 struct audio_usecase *usecase;
1332 bool ret = true;
1333
1334 list_for_each(node, &adev->usecase_list) {
1335 usecase = node_to_item(node, struct audio_usecase, list);
1336 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1337 /*
1338 * If voice call is already existing, do not proceed further to avoid
1339 * disabling/enabling both RX and TX devices, CSD calls, etc.
1340 * Once the voice call done, the HDMI channels can be configured to
1341 * max channels of remaining use cases.
1342 */
1343 if (usecase->id == USECASE_VOICE_CALL) {
1344 ALOGD("%s: voice call is active, no change in HDMI channels",
1345 __func__);
1346 ret = false;
1347 break;
1348 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1349 ALOGD("%s: multi channel playback is active, "
1350 "no change in HDMI channels", __func__);
1351 ret = false;
1352 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001353 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001354 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001355 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1356 ", no change in HDMI channels", __func__,
1357 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001358 ret = false;
1359 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001360 }
1361 }
1362 }
1363 return ret;
1364}
1365
1366static int check_and_set_hdmi_channels(struct audio_device *adev,
1367 unsigned int channels)
1368{
1369 struct listnode *node;
1370 struct audio_usecase *usecase;
1371
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001372 unsigned int supported_channels = platform_edid_get_max_channels(
1373 adev->platform);
1374 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001375 /* Check if change in HDMI channel config is allowed */
1376 if (!allow_hdmi_channel_config(adev))
1377 return 0;
1378
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001379 if (channels > supported_channels)
1380 channels = supported_channels;
1381
Eric Laurent07eeafd2013-10-06 12:52:49 -07001382 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001383 ALOGD("%s: Requested channels are same as current channels(%d)",
1384 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001385 return 0;
1386 }
1387
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001388 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001390 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001391 adev->cur_hdmi_channels = channels;
1392
1393 /*
1394 * Deroute all the playback streams routed to HDMI so that
1395 * the back end is deactivated. Note that backend will not
1396 * be deactivated if any one stream is connected to it.
1397 */
1398 list_for_each(node, &adev->usecase_list) {
1399 usecase = node_to_item(node, struct audio_usecase, list);
1400 if (usecase->type == PCM_PLAYBACK &&
1401 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001402 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403 }
1404 }
1405
1406 /*
1407 * Enable all the streams disabled above. Now the HDMI backend
1408 * will be activated with new channel configuration
1409 */
1410 list_for_each(node, &adev->usecase_list) {
1411 usecase = node_to_item(node, struct audio_usecase, list);
1412 if (usecase->type == PCM_PLAYBACK &&
1413 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001414 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001415 }
1416 }
1417
1418 return 0;
1419}
1420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421static int stop_output_stream(struct stream_out *out)
1422{
1423 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 struct audio_usecase *uc_info;
1425 struct audio_device *adev = out->dev;
1426
Eric Laurent994a6932013-07-17 11:51:42 -07001427 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001428 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 uc_info = get_usecase_from_list(adev, out->usecase);
1430 if (uc_info == NULL) {
1431 ALOGE("%s: Could not find the usecase (%d) in the list",
1432 __func__, out->usecase);
1433 return -EINVAL;
1434 }
1435
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001436 if (is_offload_usecase(out->usecase) &&
1437 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001438 if (adev->visualizer_stop_output != NULL)
1439 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001440
1441 audio_extn_dts_remove_state_notifier_node(out->usecase);
1442
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001443 if (adev->offload_effects_stop_output != NULL)
1444 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1445 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001446
Eric Laurent150dbfe2013-02-27 14:31:02 -08001447 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449
1450 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001451 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001453 list_remove(&uc_info->list);
1454 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001456 if (is_offload_usecase(out->usecase) &&
1457 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1458 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1459 ALOGV("Disable passthrough , reset mixer to pcm");
1460 /* NO_PASSTHROUGH */
1461 out->compr_config.codec->compr_passthr = 0;
1462 audio_extn_dolby_set_hdmi_config(adev, out);
1463 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1464 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001465 /* Must be called after removing the usecase from list */
1466 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1467 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1468
Eric Laurent994a6932013-07-17 11:51:42 -07001469 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 return ret;
1471}
1472
1473int start_output_stream(struct stream_out *out)
1474{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001476 int sink_channels = 0;
1477 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 struct audio_usecase *uc_info;
1479 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301480 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001482 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1483 ret = -EINVAL;
1484 goto error_config;
1485 }
1486
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301487 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1488 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1489 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301490
Naresh Tanniru80659832014-06-04 18:17:56 +05301491 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301492 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301493 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301494 goto error_config;
1495 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301496
Eric Laurentb23d5282013-05-14 15:27:20 -07001497 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 if (out->pcm_device_id < 0) {
1499 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1500 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001501 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001502 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 }
1504
1505 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001506
1507 if (!uc_info) {
1508 ret = -ENOMEM;
1509 goto error_config;
1510 }
1511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 uc_info->id = out->usecase;
1513 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001514 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 uc_info->devices = out->devices;
1516 uc_info->in_snd_device = SND_DEVICE_NONE;
1517 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001518 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001519 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001520 if (is_offload_usecase(out->usecase)) {
1521 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001522 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1523 }
1524 }
Mingming Yin9c041392014-05-01 15:37:31 -07001525 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1526 if (!strncmp("true", prop_value, 4)) {
1527 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001528 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1529 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001530 check_and_set_hdmi_channels(adev, sink_channels);
1531 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001532 if (is_offload_usecase(out->usecase)) {
1533 unsigned int ch_count = out->compr_config.codec->ch_in;
1534 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1535 /* backend channel config for passthrough stream is stereo */
1536 ch_count = 2;
1537 check_and_set_hdmi_channels(adev, ch_count);
1538 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001539 check_and_set_hdmi_channels(adev, out->config.channels);
1540 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001541 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001542 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001543 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 select_devices(adev, out->usecase);
1546
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001547 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1548 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001549 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001550 unsigned int flags = PCM_OUT;
1551 unsigned int pcm_open_retry_count = 0;
1552 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1553 flags |= PCM_MMAP | PCM_NOIRQ;
1554 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1555 } else
1556 flags |= PCM_MONOTONIC;
1557
1558 while (1) {
1559 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1560 flags, &out->config);
1561 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1562 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1563 if (out->pcm != NULL) {
1564 pcm_close(out->pcm);
1565 out->pcm = NULL;
1566 }
1567 if (pcm_open_retry_count-- == 0) {
1568 ret = -EIO;
1569 goto error_open;
1570 }
1571 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1572 continue;
1573 }
1574 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001575 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001576 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1577 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001578 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001579 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1580 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001582 out->compr = compress_open(adev->snd_card,
1583 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001584 COMPRESS_IN, &out->compr_config);
1585 if (out->compr && !is_compress_ready(out->compr)) {
1586 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1587 compress_close(out->compr);
1588 out->compr = NULL;
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 if (out->offload_callback)
1593 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001594
Fred Oh3f43e742015-03-04 18:42:34 -08001595 /* Since small bufs uses blocking writes, a write will be blocked
1596 for the default max poll time (20s) in the event of an SSR.
1597 Reduce the poll time to observe and deal with SSR faster.
1598 */
1599 if (out->use_small_bufs) {
1600 compress_set_max_poll_wait(out->compr, 1000);
1601 }
1602
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001603 audio_extn_dts_create_state_notifier_node(out->usecase);
1604 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1605 popcount(out->channel_mask),
1606 out->playback_started);
1607
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001608#ifdef DS1_DOLBY_DDP_ENABLED
1609 if (audio_extn_is_dolby_format(out->format))
1610 audio_extn_dolby_send_ddp_endp_params(adev);
1611#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001612 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1613 if (adev->visualizer_start_output != NULL)
1614 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1615 if (adev->offload_effects_start_output != NULL)
1616 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001617 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 }
Eric Laurent994a6932013-07-17 11:51:42 -07001620 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001624error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626}
1627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628static int check_input_parameters(uint32_t sample_rate,
1629 audio_format_t format,
1630 int channel_count)
1631{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001632 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001634 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001635 !voice_extn_compress_voip_is_format_supported(format) &&
1636 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001637
1638 switch (channel_count) {
1639 case 1:
1640 case 2:
1641 case 6:
1642 break;
1643 default:
1644 ret = -EINVAL;
1645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
1647 switch (sample_rate) {
1648 case 8000:
1649 case 11025:
1650 case 12000:
1651 case 16000:
1652 case 22050:
1653 case 24000:
1654 case 32000:
1655 case 44100:
1656 case 48000:
1657 break;
1658 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001659 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 }
1661
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001662 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663}
1664
1665static size_t get_input_buffer_size(uint32_t sample_rate,
1666 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001667 int channel_count,
1668 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669{
1670 size_t size = 0;
1671
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001672 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1673 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001675 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001676 if (is_low_latency)
1677 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001678 /* ToDo: should use frame_size computed based on the format and
1679 channel_count here. */
1680 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001682 /* make sure the size is multiple of 32 bytes
1683 * At 48 kHz mono 16-bit PCM:
1684 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1685 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1686 */
1687 size += 0x1f;
1688 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001689
1690 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691}
1692
1693static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1694{
1695 struct stream_out *out = (struct stream_out *)stream;
1696
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001697 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698}
1699
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001700static int out_set_sample_rate(struct audio_stream *stream __unused,
1701 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702{
1703 return -ENOSYS;
1704}
1705
1706static size_t out_get_buffer_size(const struct audio_stream *stream)
1707{
1708 struct stream_out *out = (struct stream_out *)stream;
1709
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001710 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001711 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001712 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1713 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001715 return out->config.period_size *
1716 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717}
1718
1719static uint32_t out_get_channels(const struct audio_stream *stream)
1720{
1721 struct stream_out *out = (struct stream_out *)stream;
1722
1723 return out->channel_mask;
1724}
1725
1726static audio_format_t out_get_format(const struct audio_stream *stream)
1727{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 struct stream_out *out = (struct stream_out *)stream;
1729
1730 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731}
1732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001733static int out_set_format(struct audio_stream *stream __unused,
1734 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735{
1736 return -ENOSYS;
1737}
1738
1739static int out_standby(struct audio_stream *stream)
1740{
1741 struct stream_out *out = (struct stream_out *)stream;
1742 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001743
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301744 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1745 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001746 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1747 /* Ignore standby in case of voip call because the voip output
1748 * stream is closed in adev_close_output_stream()
1749 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301750 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001751 return 0;
1752 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001756 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001758 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 if (out->pcm) {
1760 pcm_close(out->pcm);
1761 out->pcm = NULL;
1762 }
1763 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001764 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001766 out->gapless_mdata.encoder_delay = 0;
1767 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768 if (out->compr != NULL) {
1769 compress_close(out->compr);
1770 out->compr = NULL;
1771 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001772 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001774 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 }
1776 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001777 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 return 0;
1779}
1780
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001781static int out_dump(const struct audio_stream *stream __unused,
1782 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783{
1784 return 0;
1785}
1786
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001787static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1788{
1789 int ret = 0;
1790 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001791 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001792
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001794 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001795 return -EINVAL;
1796 }
1797
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001798 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1799 if (ret >= 0) {
1800 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1801 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1802 ALOGV("ADTS format is set in offload mode");
1803 }
1804 out->send_new_metadata = 1;
1805 }
1806
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301807 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001808
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1810 if(ret >= 0)
1811 is_meta_data_params = true;
1812 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301813 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001814 is_meta_data_params = true;
1815 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301816 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001817 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001818 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1819 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301821 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1824 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001825 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301826 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 }
1828
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001829 if(!is_meta_data_params) {
1830 ALOGV("%s: Not gapless meta data params", __func__);
1831 return 0;
1832 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001833 out->send_new_metadata = 1;
1834 ALOGV("%s new encoder delay %u and padding %u", __func__,
1835 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1836
1837 return 0;
1838}
1839
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001840static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1841{
1842 return out == adev->primary_output || out == adev->voice_tx_output;
1843}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1846{
1847 struct stream_out *out = (struct stream_out *)stream;
1848 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001849 struct audio_usecase *usecase;
1850 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 struct str_parms *parms;
1852 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001853 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001854 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855
sangwoobc677242013-08-08 16:53:43 +09001856 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301859 if (!parms)
1860 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001861 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1862 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001865 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301868 * When HDMI cable is unplugged/usb hs is disconnected the
1869 * music playback is paused and the policy manager sends routing=0
1870 * But the audioflingercontinues to write data until standby time
1871 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 * Avoid this by routing audio to speaker until standby.
1873 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301874 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1875 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001877 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1878 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 }
1880
1881 /*
1882 * select_devices() call below switches all the usecases on the same
1883 * backend to the new device. Refer to check_usecases_codec_backend() in
1884 * the select_devices(). But how do we undo this?
1885 *
1886 * For example, music playback is active on headset (deep-buffer usecase)
1887 * and if we go to ringtones and select a ringtone, low-latency usecase
1888 * will be started on headset+speaker. As we can't enable headset+speaker
1889 * and headset devices at the same time, select_devices() switches the music
1890 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1891 * So when the ringtone playback is completed, how do we undo the same?
1892 *
1893 * We are relying on the out_set_parameters() call on deep-buffer output,
1894 * once the ringtone playback is ended.
1895 * NOTE: We should not check if the current devices are same as new devices.
1896 * Because select_devices() must be called to switch back the music
1897 * playback to headset.
1898 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001899 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 out->devices = val;
1901
1902 if (!out->standby)
1903 select_devices(adev, out->usecase);
1904
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001905 if (output_drives_call(adev, out)) {
1906 if(!voice_is_in_call(adev)) {
1907 if (adev->mode == AUDIO_MODE_IN_CALL) {
1908 adev->current_call_output = out;
1909 ret = voice_start_call(adev);
1910 }
1911 } else {
1912 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001913 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001914 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001915 }
1916 }
1917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001919 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001921
1922 if (out == adev->primary_output) {
1923 pthread_mutex_lock(&adev->lock);
1924 audio_extn_set_parameters(adev, parms);
1925 pthread_mutex_unlock(&adev->lock);
1926 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001927 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001928 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001929 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001930
1931 audio_extn_dts_create_state_notifier_node(out->usecase);
1932 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1933 popcount(out->channel_mask),
1934 out->playback_started);
1935
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001936 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301940error:
Eric Laurent994a6932013-07-17 11:51:42 -07001941 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 return ret;
1943}
1944
1945static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1946{
1947 struct stream_out *out = (struct stream_out *)stream;
1948 struct str_parms *query = str_parms_create_str(keys);
1949 char *str;
1950 char value[256];
1951 struct str_parms *reply = str_parms_create();
1952 size_t i, j;
1953 int ret;
1954 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001955
1956 if (!query || !reply) {
1957 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1958 return NULL;
1959 }
1960
Eric Laurent994a6932013-07-17 11:51:42 -07001961 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1963 if (ret >= 0) {
1964 value[0] = '\0';
1965 i = 0;
1966 while (out->supported_channel_masks[i] != 0) {
1967 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1968 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1969 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001970 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001972 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 first = false;
1974 break;
1975 }
1976 }
1977 i++;
1978 }
1979 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1980 str = str_parms_to_str(reply);
1981 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001982 voice_extn_out_get_parameters(out, query, reply);
1983 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001984 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001985 free(str);
1986 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001987 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001989
1990 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1991 if (ret >= 0) {
1992 value[0] = '\0';
1993 i = 0;
1994 first = true;
1995 while (out->supported_formats[i] != 0) {
1996 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1997 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1998 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001999 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002000 }
2001 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2002 first = false;
2003 break;
2004 }
2005 }
2006 i++;
2007 }
2008 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2009 str = str_parms_to_str(reply);
2010 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 str_parms_destroy(query);
2012 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002013 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 return str;
2015}
2016
2017static uint32_t out_get_latency(const struct audio_stream_out *stream)
2018{
2019 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002020 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002023 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002024 } else {
2025 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002027 }
2028
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302029 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002030 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031}
2032
2033static int out_set_volume(struct audio_stream_out *stream, float left,
2034 float right)
2035{
Eric Laurenta9024de2013-04-04 09:19:12 -07002036 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 int volume[2];
2038
Eric Laurenta9024de2013-04-04 09:19:12 -07002039 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2040 /* only take left channel into account: the API is for stereo anyway */
2041 out->muted = (left == 0.0f);
2042 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002043 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002044 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2045 /*
2046 * Set mute or umute on HDMI passthrough stream.
2047 * Only take left channel into account.
2048 * Mute is 0 and unmute 1
2049 */
2050 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2051 } else {
2052 char mixer_ctl_name[128];
2053 struct audio_device *adev = out->dev;
2054 struct mixer_ctl *ctl;
2055 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002056 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002058 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2059 "Compress Playback %d Volume", pcm_device_id);
2060 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2061 if (!ctl) {
2062 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2063 __func__, mixer_ctl_name);
2064 return -EINVAL;
2065 }
2066 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2067 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2068 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2069 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002071 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 return -ENOSYS;
2074}
2075
2076static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2077 size_t bytes)
2078{
2079 struct stream_out *out = (struct stream_out *)stream;
2080 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302081 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002082 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302085
Naresh Tanniru80659832014-06-04 18:17:56 +05302086 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002087 // increase written size during SSR to avoid mismatch
2088 // with the written frames count in AF
2089 if (!is_offload_usecase(out->usecase))
2090 out->written += bytes / (out->config.channels * sizeof(short));
2091
Naresh Tanniru80659832014-06-04 18:17:56 +05302092 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302093 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302094 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302095 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002096 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302097 //during SSR for compress usecase we should return error to flinger
2098 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2099 pthread_mutex_unlock(&out->lock);
2100 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302101 }
2102 }
2103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002105 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002106 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002107 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2108 ret = voice_extn_compress_voip_start_output_stream(out);
2109 else
2110 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002111 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002114 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 goto exit;
2116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002119 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002120 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002121 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002122 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002123 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2124 out->send_new_metadata = 0;
2125 }
2126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302128 if (ret < 0)
2129 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002131 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302132 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302134 } else if (-ENETRESET == ret) {
2135 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2136 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2137 pthread_mutex_unlock(&out->lock);
2138 out_standby(&out->stream.common);
2139 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302141 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002143 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 out->playback_started = 1;
2145 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002146
2147 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2148 popcount(out->channel_mask),
2149 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150 }
2151 pthread_mutex_unlock(&out->lock);
2152 return ret;
2153 } else {
2154 if (out->pcm) {
2155 if (out->muted)
2156 memset((void *)buffer, 0, bytes);
2157 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002158 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2159 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2160 else
2161 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302162 if (ret < 0)
2163 ret = -errno;
2164 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002165 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 }
2168
2169exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302170 /* ToDo: There may be a corner case when SSR happens back to back during
2171 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302172 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302173 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302174 }
2175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176 pthread_mutex_unlock(&out->lock);
2177
2178 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002179 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002180 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302181 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302182 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302183 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302184 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302185 out->standby = true;
2186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002188 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302189 out_get_sample_rate(&out->stream.common));
2190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 }
2192 return bytes;
2193}
2194
2195static int out_get_render_position(const struct audio_stream_out *stream,
2196 uint32_t *dsp_frames)
2197{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002198 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302199 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002200
2201 if (dsp_frames == NULL)
2202 return -EINVAL;
2203
2204 *dsp_frames = 0;
2205 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002206 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 pthread_mutex_lock(&out->lock);
2208 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302209 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302211 if (ret < 0)
2212 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 ALOGVV("%s rendered frames %d sample_rate %d",
2214 __func__, *dsp_frames, out->sample_rate);
2215 }
2216 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302217 if (-ENETRESET == ret) {
2218 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2219 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2220 return -EINVAL;
2221 } else if(ret < 0) {
2222 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2223 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302224 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2225 /*
2226 * Handle corner case where compress session is closed during SSR
2227 * and timestamp is queried
2228 */
2229 ALOGE(" ERROR: sound card not active, return error");
2230 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302231 } else {
2232 return 0;
2233 }
Zhou Song32a556e2015-05-05 10:46:56 +08002234 } else if (audio_is_linear_pcm(out->format)) {
2235 *dsp_frames = out->written;
2236 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 } else
2238 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239}
2240
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002241static int out_add_audio_effect(const struct audio_stream *stream __unused,
2242 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243{
2244 return 0;
2245}
2246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002247static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2248 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249{
2250 return 0;
2251}
2252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002253static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2254 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255{
2256 return -EINVAL;
2257}
2258
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002259static int out_get_presentation_position(const struct audio_stream_out *stream,
2260 uint64_t *frames, struct timespec *timestamp)
2261{
2262 struct stream_out *out = (struct stream_out *)stream;
2263 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002264 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002265
2266 pthread_mutex_lock(&out->lock);
2267
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002268 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002269 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302270 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002271 &out->sample_rate);
2272 ALOGVV("%s rendered frames %ld sample_rate %d",
2273 __func__, dsp_frames, out->sample_rate);
2274 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302275 if (ret < 0)
2276 ret = -errno;
2277 if (-ENETRESET == ret) {
2278 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2279 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2280 ret = -EINVAL;
2281 } else
2282 ret = 0;
2283
Eric Laurent949a0892013-09-20 09:20:13 -07002284 /* this is the best we can do */
2285 clock_gettime(CLOCK_MONOTONIC, timestamp);
2286 }
2287 } else {
2288 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002289 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002290 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2291 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002292 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002293 // This adjustment accounts for buffering after app processor.
2294 // It is based on estimated DSP latency per use case, rather than exact.
2295 signed_frames -=
2296 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2297
Eric Laurent949a0892013-09-20 09:20:13 -07002298 // It would be unusual for this value to be negative, but check just in case ...
2299 if (signed_frames >= 0) {
2300 *frames = signed_frames;
2301 ret = 0;
2302 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002303 }
2304 }
2305 }
2306
2307 pthread_mutex_unlock(&out->lock);
2308
2309 return ret;
2310}
2311
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312static int out_set_callback(struct audio_stream_out *stream,
2313 stream_callback_t callback, void *cookie)
2314{
2315 struct stream_out *out = (struct stream_out *)stream;
2316
2317 ALOGV("%s", __func__);
2318 pthread_mutex_lock(&out->lock);
2319 out->offload_callback = callback;
2320 out->offload_cookie = cookie;
2321 pthread_mutex_unlock(&out->lock);
2322 return 0;
2323}
2324
2325static int out_pause(struct audio_stream_out* stream)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328 int status = -ENOSYS;
2329 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002330 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002331 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 pthread_mutex_lock(&out->lock);
2333 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302334 struct audio_device *adev = out->dev;
2335 int snd_scard_state = get_snd_card_state(adev);
2336
2337 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2338 status = compress_pause(out->compr);
2339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002341
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302342 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002343 audio_extn_dts_notify_playback_state(out->usecase, 0,
2344 out->sample_rate, popcount(out->channel_mask),
2345 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 }
2347 pthread_mutex_unlock(&out->lock);
2348 }
2349 return status;
2350}
2351
2352static int out_resume(struct audio_stream_out* stream)
2353{
2354 struct stream_out *out = (struct stream_out *)stream;
2355 int status = -ENOSYS;
2356 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002357 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002358 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 status = 0;
2360 pthread_mutex_lock(&out->lock);
2361 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302362 struct audio_device *adev = out->dev;
2363 int snd_scard_state = get_snd_card_state(adev);
2364
2365 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2366 status = compress_resume(out->compr);
2367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002369
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302370 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002371 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2372 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 }
2374 pthread_mutex_unlock(&out->lock);
2375 }
2376 return status;
2377}
2378
2379static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2380{
2381 struct stream_out *out = (struct stream_out *)stream;
2382 int status = -ENOSYS;
2383 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002384 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 pthread_mutex_lock(&out->lock);
2386 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2387 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2388 else
2389 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2390 pthread_mutex_unlock(&out->lock);
2391 }
2392 return status;
2393}
2394
2395static int out_flush(struct audio_stream_out* stream)
2396{
2397 struct stream_out *out = (struct stream_out *)stream;
2398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002400 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 pthread_mutex_lock(&out->lock);
2402 stop_compressed_output_l(out);
2403 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002404 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 return 0;
2406 }
2407 return -ENOSYS;
2408}
2409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410/** audio_stream_in implementation **/
2411static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2412{
2413 struct stream_in *in = (struct stream_in *)stream;
2414
2415 return in->config.rate;
2416}
2417
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002418static int in_set_sample_rate(struct audio_stream *stream __unused,
2419 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420{
2421 return -ENOSYS;
2422}
2423
2424static size_t in_get_buffer_size(const struct audio_stream *stream)
2425{
2426 struct stream_in *in = (struct stream_in *)stream;
2427
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002428 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2429 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002430 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2431 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002432
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002433 return in->config.period_size *
2434 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435}
2436
2437static uint32_t in_get_channels(const struct audio_stream *stream)
2438{
2439 struct stream_in *in = (struct stream_in *)stream;
2440
2441 return in->channel_mask;
2442}
2443
2444static audio_format_t in_get_format(const struct audio_stream *stream)
2445{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002446 struct stream_in *in = (struct stream_in *)stream;
2447
2448 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449}
2450
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002451static int in_set_format(struct audio_stream *stream __unused,
2452 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453{
2454 return -ENOSYS;
2455}
2456
2457static int in_standby(struct audio_stream *stream)
2458{
2459 struct stream_in *in = (struct stream_in *)stream;
2460 struct audio_device *adev = in->dev;
2461 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302462 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2463 stream, in->usecase, use_case_table[in->usecase]);
2464
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002465 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2466 /* Ignore standby in case of voip call because the voip input
2467 * stream is closed in adev_close_input_stream()
2468 */
2469 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2470 return status;
2471 }
2472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002474 if (!in->standby && in->is_st_session) {
2475 ALOGD("%s: sound trigger pcm stop lab", __func__);
2476 audio_extn_sound_trigger_stop_lab(in);
2477 in->standby = 1;
2478 }
2479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002481 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002483 if (in->pcm) {
2484 pcm_close(in->pcm);
2485 in->pcm = NULL;
2486 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002488 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 }
2490 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002491 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 return status;
2493}
2494
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002495static int in_dump(const struct audio_stream *stream __unused,
2496 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497{
2498 return 0;
2499}
2500
2501static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2502{
2503 struct stream_in *in = (struct stream_in *)stream;
2504 struct audio_device *adev = in->dev;
2505 struct str_parms *parms;
2506 char *str;
2507 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002508 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302510 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 parms = str_parms_create_str(kvpairs);
2512
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302513 if (!parms)
2514 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002517
2518 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2519 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 val = atoi(value);
2521 /* no audio source uses val == 0 */
2522 if ((in->source != val) && (val != 0)) {
2523 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002524 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2525 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2526 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2527 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002528 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002529 err = voice_extn_compress_voip_open_input_stream(in);
2530 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002531 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002532 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002533 }
2534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 }
2536 }
2537
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002538 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2539 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002541 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 in->device = val;
2543 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002544 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002545 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
2547 }
2548
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002549done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002551 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552
2553 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302554error:
Eric Laurent994a6932013-07-17 11:51:42 -07002555 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 return ret;
2557}
2558
2559static char* in_get_parameters(const struct audio_stream *stream,
2560 const char *keys)
2561{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002562 struct stream_in *in = (struct stream_in *)stream;
2563 struct str_parms *query = str_parms_create_str(keys);
2564 char *str;
2565 char value[256];
2566 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002567
2568 if (!query || !reply) {
2569 ALOGE("in_get_parameters: failed to create query or reply");
2570 return NULL;
2571 }
2572
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002573 ALOGV("%s: enter: keys - %s", __func__, keys);
2574
2575 voice_extn_in_get_parameters(in, query, reply);
2576
2577 str = str_parms_to_str(reply);
2578 str_parms_destroy(query);
2579 str_parms_destroy(reply);
2580
2581 ALOGV("%s: exit: returns - %s", __func__, str);
2582 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583}
2584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002585static int in_set_gain(struct audio_stream_in *stream __unused,
2586 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return 0;
2589}
2590
2591static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2592 size_t bytes)
2593{
2594 struct stream_in *in = (struct stream_in *)stream;
2595 struct audio_device *adev = in->dev;
2596 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302597 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302600
2601 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302602 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302603 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302604 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302605 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002606 } else {
2607 if (in->is_st_session && !in->is_st_session_active) {
2608 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2609 ret= -EIO;;
2610 goto exit;
2611 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302612 }
2613 }
2614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002616 if (!in->is_st_session) {
2617 pthread_mutex_lock(&adev->lock);
2618 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2619 ret = voice_extn_compress_voip_start_input_stream(in);
2620 else
2621 ret = start_input_stream(in);
2622 pthread_mutex_unlock(&adev->lock);
2623 if (ret != 0) {
2624 goto exit;
2625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 }
2627 in->standby = 0;
2628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629
2630 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002631 if (audio_extn_ssr_get_enabled() &&
2632 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002633 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002634 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2635 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002636 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2637 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002638 else
2639 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302640 if (ret < 0)
2641 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 }
2643
2644 /*
2645 * Instead of writing zeroes here, we could trust the hardware
2646 * to always provide zeroes when muted.
2647 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302648 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2649 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 memset(buffer, 0, bytes);
2651
2652exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302653 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302654 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302655 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002656 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2657 session reading on LAB data. In this case do not set sound card state
2658 offline, instead mark this sound trigger session inactive to avoid
2659 further reading of LAB data from CPE driver. Marking the session
2660 inactive handles both CPE and ADSP SSR for sound trigger session */
2661 if (!in->is_st_session)
2662 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2663 else
2664 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 pthread_mutex_unlock(&in->lock);
2667
2668 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302669 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302670 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302671 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302672 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302673 in->standby = true;
2674 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302675 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002677 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002678 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302679 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 }
2681 return bytes;
2682}
2683
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002684static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685{
2686 return 0;
2687}
2688
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002689static int add_remove_audio_effect(const struct audio_stream *stream,
2690 effect_handle_t effect,
2691 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002693 struct stream_in *in = (struct stream_in *)stream;
2694 int status = 0;
2695 effect_descriptor_t desc;
2696
2697 status = (*effect)->get_descriptor(effect, &desc);
2698 if (status != 0)
2699 return status;
2700
2701 pthread_mutex_lock(&in->lock);
2702 pthread_mutex_lock(&in->dev->lock);
2703 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2704 in->enable_aec != enable &&
2705 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2706 in->enable_aec = enable;
2707 if (!in->standby)
2708 select_devices(in->dev, in->usecase);
2709 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002710 if (in->enable_ns != enable &&
2711 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2712 in->enable_ns = enable;
2713 if (!in->standby)
2714 select_devices(in->dev, in->usecase);
2715 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002716 pthread_mutex_unlock(&in->dev->lock);
2717 pthread_mutex_unlock(&in->lock);
2718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 return 0;
2720}
2721
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002722static int in_add_audio_effect(const struct audio_stream *stream,
2723 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724{
Eric Laurent994a6932013-07-17 11:51:42 -07002725 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002726 return add_remove_audio_effect(stream, effect, true);
2727}
2728
2729static int in_remove_audio_effect(const struct audio_stream *stream,
2730 effect_handle_t effect)
2731{
Eric Laurent994a6932013-07-17 11:51:42 -07002732 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002733 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734}
2735
2736static int adev_open_output_stream(struct audio_hw_device *dev,
2737 audio_io_handle_t handle,
2738 audio_devices_t devices,
2739 audio_output_flags_t flags,
2740 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002741 struct audio_stream_out **stream_out,
2742 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743{
2744 struct audio_device *adev = (struct audio_device *)dev;
2745 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002746 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002747 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302750
2751 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2752 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2753 ALOGE(" sound card is not active rejecting compress output open request");
2754 return -EINVAL;
2755 }
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2758
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302759 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2760 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2761 devices, flags, &out->stream);
2762
2763
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002764 if (!out) {
2765 return -ENOMEM;
2766 }
2767
Haynes Mathew George204045b2015-02-25 20:32:03 -08002768 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2769 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 if (devices == AUDIO_DEVICE_NONE)
2772 devices = AUDIO_DEVICE_OUT_SPEAKER;
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 out->flags = flags;
2775 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002776 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002777 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002778 out->sample_rate = config->sample_rate;
2779 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2780 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002781 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002782 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002783 out->non_blocking = 0;
2784 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785
2786 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002787 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2788 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2789 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2790
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002791 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002792 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2793 ret = read_hdmi_channel_masks(out);
2794
2795 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2796 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002797 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002798 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002800
2801 if (config->sample_rate == 0)
2802 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2803 if (config->channel_mask == 0)
2804 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2805
2806 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2809 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002811 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002813 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2814 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002815 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002816 ret = voice_extn_compress_voip_open_output_stream(out);
2817 if (ret != 0) {
2818 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2819 __func__, ret);
2820 goto error_open;
2821 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2823 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2824 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2825 ALOGE("%s: Unsupported Offload information", __func__);
2826 ret = -EINVAL;
2827 goto error_open;
2828 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002829
2830 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2831 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2832 ALOGV("read and update_pass through formats");
2833 ret = audio_extn_dolby_update_passt_formats(adev, out);
2834 if(ret != 0) {
2835 goto error_open;
2836 }
2837 if(config->offload_info.format == 0)
2838 config->offload_info.format = out->supported_formats[0];
2839 }
2840
Mingming Yin90310102013-11-13 16:57:00 -08002841 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002842 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 ALOGE("%s: Unsupported audio format", __func__);
2844 ret = -EINVAL;
2845 goto error_open;
2846 }
2847
2848 out->compr_config.codec = (struct snd_codec *)
2849 calloc(1, sizeof(struct snd_codec));
2850
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002851 if (!out->compr_config.codec) {
2852 ret = -ENOMEM;
2853 goto error_open;
2854 }
2855
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002856 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 if (config->offload_info.channel_mask)
2858 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002859 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002861 config->offload_info.channel_mask = config->channel_mask;
2862 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002863 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 out->sample_rate = config->offload_info.sample_rate;
2865
2866 out->stream.set_callback = out_set_callback;
2867 out->stream.pause = out_pause;
2868 out->stream.resume = out_resume;
2869 out->stream.drain = out_drain;
2870 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002871 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002873 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002874 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002875 audio_extn_dolby_get_snd_codec_id(adev, out,
2876 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002877 else
2878 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002880 if (audio_is_offload_pcm(config->offload_info.format)) {
2881 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002882 platform_get_pcm_offload_buffer_size(&config->offload_info);
2883 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2884 out->compr_config.fragment_size =
2885 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002886 } else {
2887 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002888 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002889 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2891 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302892 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 out->compr_config.codec->bit_rate =
2894 config->offload_info.bit_rate;
2895 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002896 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002898 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002899 /*TODO: Do we need to change it for passthrough */
2900 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901
Mingming Yin3ee55c62014-08-04 14:23:35 -07002902 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2903 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002904 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2905 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002906 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2908
Mingming Yin3ee55c62014-08-04 14:23:35 -07002909 if (out->bit_width == 24) {
2910 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2911 }
2912
Amit Shekhar6f461b12014-08-01 14:52:58 -07002913 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002914 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002915
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2917 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002918
Alexy Josephaa54c872014-12-03 02:46:47 -08002919 if (config->offload_info.use_small_bufs) {
2920 //this flag is set from framework only if its for PCM formats
2921 //no need to check for PCM format again
2922 out->non_blocking = 0;
2923 out->use_small_bufs = true;
2924 ALOGI("Keep write blocking for small buff: non_blockling %d",
2925 out->non_blocking);
2926 }
2927
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002928 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002929 out->offload_state = OFFLOAD_STATE_IDLE;
2930 out->playback_started = 0;
2931
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002932 audio_extn_dts_create_state_notifier_node(out->usecase);
2933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 create_offload_callback_thread(out);
2935 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2936 __func__, config->offload_info.version,
2937 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002938 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002939 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002940 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2941 ret = voice_check_and_set_incall_music_usecase(adev, out);
2942 if (ret != 0) {
2943 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2944 __func__, ret);
2945 goto error_open;
2946 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002947 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2948 if (config->sample_rate == 0)
2949 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2950 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2951 config->sample_rate != 8000) {
2952 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2953 ret = -EINVAL;
2954 goto error_open;
2955 }
2956 out->sample_rate = config->sample_rate;
2957 out->config.rate = config->sample_rate;
2958 if (config->format == AUDIO_FORMAT_DEFAULT)
2959 config->format = AUDIO_FORMAT_PCM_16_BIT;
2960 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2961 config->format = AUDIO_FORMAT_PCM_16_BIT;
2962 ret = -EINVAL;
2963 goto error_open;
2964 }
2965 out->format = config->format;
2966 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2967 out->config = pcm_config_afe_proxy_playback;
2968 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002969 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002970 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2972 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002974 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2975 format = AUDIO_FORMAT_PCM_16_BIT;
2976 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2977 out->config = pcm_config_deep_buffer;
2978 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002979 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002980 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002981 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002982 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002983 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002984 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 }
2986
Amit Shekhar1d896042014-10-03 13:16:09 -07002987 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2988 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002989 /* TODO remove this hardcoding and check why width is zero*/
2990 if (out->bit_width == 0)
2991 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002992 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2993 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002994 devices, flags, format, out->sample_rate,
Manish Dewanganf48adb42015-05-27 10:17:41 +05302995 out->bit_width, out->channel_mask,
2996 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002997 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2998 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2999 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003000 if(adev->primary_output == NULL)
3001 adev->primary_output = out;
3002 else {
3003 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003004 ret = -EEXIST;
3005 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003006 }
3007 }
3008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 /* Check if this usecase is already existing */
3010 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003011 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3012 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003015 ret = -EEXIST;
3016 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 }
3018 pthread_mutex_unlock(&adev->lock);
3019
3020 out->stream.common.get_sample_rate = out_get_sample_rate;
3021 out->stream.common.set_sample_rate = out_set_sample_rate;
3022 out->stream.common.get_buffer_size = out_get_buffer_size;
3023 out->stream.common.get_channels = out_get_channels;
3024 out->stream.common.get_format = out_get_format;
3025 out->stream.common.set_format = out_set_format;
3026 out->stream.common.standby = out_standby;
3027 out->stream.common.dump = out_dump;
3028 out->stream.common.set_parameters = out_set_parameters;
3029 out->stream.common.get_parameters = out_get_parameters;
3030 out->stream.common.add_audio_effect = out_add_audio_effect;
3031 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3032 out->stream.get_latency = out_get_latency;
3033 out->stream.set_volume = out_set_volume;
3034 out->stream.write = out_write;
3035 out->stream.get_render_position = out_get_render_position;
3036 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003037 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003040 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003041 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
3043 config->format = out->stream.common.get_format(&out->stream.common);
3044 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3045 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3046
3047 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303048 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3049 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003050
3051 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3052 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3053 popcount(out->channel_mask), out->playback_started);
3054
Eric Laurent994a6932013-07-17 11:51:42 -07003055 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003057
3058error_open:
3059 free(out);
3060 *stream_out = NULL;
3061 ALOGD("%s: exit: ret %d", __func__, ret);
3062 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003065static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 struct audio_stream_out *stream)
3067{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 struct stream_out *out = (struct stream_out *)stream;
3069 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003070 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303072 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003076 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303077 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 if(ret != 0)
3079 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3080 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003081 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 out_standby(&stream->common);
3083
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003084 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003085 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003087 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 if (out->compr_config.codec != NULL)
3089 free(out->compr_config.codec);
3090 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003091
3092 if (adev->voice_tx_output == out)
3093 adev->voice_tx_output = NULL;
3094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 pthread_cond_destroy(&out->cond);
3096 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003098 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099}
3100
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003101static void close_compress_sessions(struct audio_device *adev)
3102{
Mingming Yin7b762e72015-03-04 13:47:32 -08003103 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303104 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003105 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003106 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303107
3108 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003109 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303110 if (is_offload_usecase(usecase->id)) {
3111 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3113 out = usecase->stream.out;
3114 pthread_mutex_unlock(&adev->lock);
3115 out_standby(&out->stream.common);
3116 pthread_mutex_lock(&adev->lock);
3117 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303118 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003119 }
3120 pthread_mutex_unlock(&adev->lock);
3121}
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3124{
3125 struct audio_device *adev = (struct audio_device *)dev;
3126 struct str_parms *parms;
3127 char *str;
3128 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003129 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003130 int ret;
3131 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003133 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303136 if (!parms)
3137 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003138 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3139 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303140 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303142 struct listnode *node;
3143 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003146 //close compress sessions on OFFLINE status
3147 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303148 } else if (strstr(snd_card_status, "ONLINE")) {
3149 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303150 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303152 }
3153
3154 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003155 status = voice_set_parameters(adev, parms);
3156 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003157 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 status = platform_set_parameters(adev->platform, parms);
3160 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003161 goto done;
3162
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003163 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3164 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003165 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3167 adev->bluetooth_nrec = true;
3168 else
3169 adev->bluetooth_nrec = false;
3170 }
3171
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003172 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3173 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3175 adev->screen_off = false;
3176 else
3177 adev->screen_off = true;
3178 }
3179
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 ret = str_parms_get_int(parms, "rotation", &val);
3181 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003182 bool reverse_speakers = false;
3183 switch(val) {
3184 // FIXME: note that the code below assumes that the speakers are in the correct placement
3185 // relative to the user when the device is rotated 90deg from its default rotation. This
3186 // assumption is device-specific, not platform-specific like this code.
3187 case 270:
3188 reverse_speakers = true;
3189 break;
3190 case 0:
3191 case 90:
3192 case 180:
3193 break;
3194 default:
3195 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003196 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 if (status == 0) {
3199 if (adev->speaker_lr_swap != reverse_speakers) {
3200 adev->speaker_lr_swap = reverse_speakers;
3201 // only update the selected device if there is active pcm playback
3202 struct audio_usecase *usecase;
3203 struct listnode *node;
3204 list_for_each(node, &adev->usecase_list) {
3205 usecase = node_to_item(node, struct audio_usecase, list);
3206 if (usecase->type == PCM_PLAYBACK) {
3207 select_devices(adev, usecase->id);
3208 break;
3209 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003210 }
3211 }
3212 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003213 }
3214
Mingming Yin514a8bc2014-07-29 15:22:21 -07003215 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3216 if (ret >= 0) {
3217 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3218 adev->bt_wb_speech_enabled = true;
3219 else
3220 adev->bt_wb_speech_enabled = false;
3221 }
3222
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003223 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3224 if (ret >= 0) {
3225 val = atoi(value);
3226 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3227 ALOGV("cache new edid");
3228 platform_cache_edid(adev->platform);
3229 }
3230 }
3231
3232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3233 if (ret >= 0) {
3234 val = atoi(value);
3235 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3236 ALOGV("invalidate cached edid");
3237 platform_invalidate_edid(adev->platform);
3238 }
3239 }
3240
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003241 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003242
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003243done:
3244 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003245 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303246error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003247 ALOGV("%s: exit with code(%d)", __func__, status);
3248 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249}
3250
3251static char* adev_get_parameters(const struct audio_hw_device *dev,
3252 const char *keys)
3253{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003254 struct audio_device *adev = (struct audio_device *)dev;
3255 struct str_parms *reply = str_parms_create();
3256 struct str_parms *query = str_parms_create_str(keys);
3257 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303258 char value[256] = {0};
3259 int ret = 0;
3260
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003261 if (!query || !reply) {
3262 ALOGE("adev_get_parameters: failed to create query or reply");
3263 return NULL;
3264 }
3265
Naresh Tannirud7205b62014-06-20 02:54:48 +05303266 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3267 sizeof(value));
3268 if (ret >=0) {
3269 int val = 1;
3270 pthread_mutex_lock(&adev->snd_card_status.lock);
3271 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3272 val = 0;
3273 pthread_mutex_unlock(&adev->snd_card_status.lock);
3274 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3275 goto exit;
3276 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003277
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003278 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003279 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003280 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003281 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303282 pthread_mutex_unlock(&adev->lock);
3283
Naresh Tannirud7205b62014-06-20 02:54:48 +05303284exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003285 str = str_parms_to_str(reply);
3286 str_parms_destroy(query);
3287 str_parms_destroy(reply);
3288
3289 ALOGV("%s: exit: returns - %s", __func__, str);
3290 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291}
3292
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003293static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294{
3295 return 0;
3296}
3297
3298static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3299{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003300 int ret;
3301 struct audio_device *adev = (struct audio_device *)dev;
3302 pthread_mutex_lock(&adev->lock);
3303 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003304 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003305 pthread_mutex_unlock(&adev->lock);
3306 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307}
3308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003309static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3310 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311{
3312 return -ENOSYS;
3313}
3314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003315static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3316 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317{
3318 return -ENOSYS;
3319}
3320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003321static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3322 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323{
3324 return -ENOSYS;
3325}
3326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003327static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3328 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329{
3330 return -ENOSYS;
3331}
3332
3333static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3334{
3335 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 pthread_mutex_lock(&adev->lock);
3338 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003339 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003341 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3342 voice_is_in_call(adev)) {
3343 voice_stop_call(adev);
3344 adev->current_call_output = NULL;
3345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 }
3347 pthread_mutex_unlock(&adev->lock);
3348 return 0;
3349}
3350
3351static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3352{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003353 int ret;
3354
3355 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003356 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003357 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3358 pthread_mutex_unlock(&adev->lock);
3359
3360 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361}
3362
3363static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3364{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003365 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 return 0;
3367}
3368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003369static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 const struct audio_config *config)
3371{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003372 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003374 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3375 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376}
3377
3378static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003379 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 audio_devices_t devices,
3381 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003382 struct audio_stream_in **stream_in,
3383 audio_input_flags_t flags __unused,
3384 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003385 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386{
3387 struct audio_device *adev = (struct audio_device *)dev;
3388 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003389 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003390 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003391 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 *stream_in = NULL;
3394 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3395 return -EINVAL;
3396
3397 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003398
3399 if (!in) {
3400 ALOGE("failed to allocate input stream");
3401 return -ENOMEM;
3402 }
3403
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303404 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003405 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3406 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003408 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 in->stream.common.get_sample_rate = in_get_sample_rate;
3411 in->stream.common.set_sample_rate = in_set_sample_rate;
3412 in->stream.common.get_buffer_size = in_get_buffer_size;
3413 in->stream.common.get_channels = in_get_channels;
3414 in->stream.common.get_format = in_get_format;
3415 in->stream.common.set_format = in_set_format;
3416 in->stream.common.standby = in_standby;
3417 in->stream.common.dump = in_dump;
3418 in->stream.common.set_parameters = in_set_parameters;
3419 in->stream.common.get_parameters = in_get_parameters;
3420 in->stream.common.add_audio_effect = in_add_audio_effect;
3421 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3422 in->stream.set_gain = in_set_gain;
3423 in->stream.read = in_read;
3424 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3425
3426 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003427 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 in->standby = 1;
3430 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003431 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
3433 /* Update config params with the requested sample rate and channels */
3434 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003435 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3436 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3437 is_low_latency = true;
3438#if LOW_LATENCY_CAPTURE_USE_CASE
3439 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3440#endif
3441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003444 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003446 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303447 if (adev->mode != AUDIO_MODE_IN_CALL) {
3448 ret = -EINVAL;
3449 goto err_open;
3450 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003451 if (config->sample_rate == 0)
3452 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3453 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3454 config->sample_rate != 8000) {
3455 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3456 ret = -EINVAL;
3457 goto err_open;
3458 }
3459 if (config->format == AUDIO_FORMAT_DEFAULT)
3460 config->format = AUDIO_FORMAT_PCM_16_BIT;
3461 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3462 config->format = AUDIO_FORMAT_PCM_16_BIT;
3463 ret = -EINVAL;
3464 goto err_open;
3465 }
3466
3467 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3468 in->config = pcm_config_afe_proxy_record;
3469 in->config.channels = channel_count;
3470 in->config.rate = config->sample_rate;
3471 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003472 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003473 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003474 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3475 ret = -EINVAL;
3476 goto err_open;
3477 }
3478 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003479 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003480 }
Mingming Yine62d7842013-10-25 16:26:03 -07003481 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003482 audio_extn_compr_cap_format_supported(config->format) &&
3483 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003484 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003485 } else {
3486 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003487 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003488 buffer_size = get_input_buffer_size(config->sample_rate,
3489 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003490 channel_count,
3491 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003492 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003493 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3494 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3495 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3496 (in->config.rate == 8000 || in->config.rate == 16000) &&
3497 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3498 voice_extn_compress_voip_open_input_stream(in);
3499 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003500 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003502 /* This stream could be for sound trigger lab,
3503 get sound trigger pcm if present */
3504 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303505 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003508 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003509 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
3511err_open:
3512 free(in);
3513 *stream_in = NULL;
3514 return ret;
3515}
3516
3517static void adev_close_input_stream(struct audio_hw_device *dev,
3518 struct audio_stream_in *stream)
3519{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003520 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003521 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003522 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303523
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303524 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003525
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303526 /* Disable echo reference while closing input stream */
3527 platform_set_echo_reference(adev->platform, false);
3528
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003529 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303530 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003531 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303532 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003533 if (ret != 0)
3534 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3535 __func__, ret);
3536 } else
3537 in_standby(&stream->common);
3538
Mingming Yin7b762e72015-03-04 13:47:32 -08003539 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003540 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003541 audio_extn_ssr_deinit();
3542 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
Mingming Yine62d7842013-10-25 16:26:03 -07003544 if(audio_extn_compr_cap_enabled() &&
3545 audio_extn_compr_cap_format_supported(in->config.format))
3546 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003547
3548 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 return;
3550}
3551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003552static int adev_dump(const audio_hw_device_t *device __unused,
3553 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554{
3555 return 0;
3556}
3557
3558static int adev_close(hw_device_t *device)
3559{
3560 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003561
3562 if (!adev)
3563 return 0;
3564
3565 pthread_mutex_lock(&adev_init_lock);
3566
3567 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003568 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003569 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003570 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003571 audio_route_free(adev->audio_route);
3572 free(adev->snd_dev_ref_cnt);
3573 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003574 free(device);
3575 adev = NULL;
3576 }
3577 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 return 0;
3579}
3580
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003581/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3582 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3583 * just that it _might_ work.
3584 */
3585static int period_size_is_plausible_for_low_latency(int period_size)
3586{
3587 switch (period_size) {
3588 case 160:
3589 case 240:
3590 case 320:
3591 case 480:
3592 return 1;
3593 default:
3594 return 0;
3595 }
3596}
3597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598static int adev_open(const hw_module_t *module, const char *name,
3599 hw_device_t **device)
3600{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003601 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003603 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3605
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003606 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003607 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003608 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003609 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003610 ALOGD("%s: returning existing instance of adev", __func__);
3611 ALOGD("%s: exit", __func__);
3612 pthread_mutex_unlock(&adev_init_lock);
3613 return 0;
3614 }
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 adev = calloc(1, sizeof(struct audio_device));
3617
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003618 if (!adev) {
3619 pthread_mutex_unlock(&adev_init_lock);
3620 return -ENOMEM;
3621 }
3622
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003623 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3626 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3627 adev->device.common.module = (struct hw_module_t *)module;
3628 adev->device.common.close = adev_close;
3629
3630 adev->device.init_check = adev_init_check;
3631 adev->device.set_voice_volume = adev_set_voice_volume;
3632 adev->device.set_master_volume = adev_set_master_volume;
3633 adev->device.get_master_volume = adev_get_master_volume;
3634 adev->device.set_master_mute = adev_set_master_mute;
3635 adev->device.get_master_mute = adev_get_master_mute;
3636 adev->device.set_mode = adev_set_mode;
3637 adev->device.set_mic_mute = adev_set_mic_mute;
3638 adev->device.get_mic_mute = adev_get_mic_mute;
3639 adev->device.set_parameters = adev_set_parameters;
3640 adev->device.get_parameters = adev_get_parameters;
3641 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3642 adev->device.open_output_stream = adev_open_output_stream;
3643 adev->device.close_output_stream = adev_close_output_stream;
3644 adev->device.open_input_stream = adev_open_input_stream;
3645 adev->device.close_input_stream = adev_close_input_stream;
3646 adev->device.dump = adev_dump;
3647
3648 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003650 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003651 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003654 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003655 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003656 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003657 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003658 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003659 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003660 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303661
3662 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3663 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003665 adev->platform = platform_init(adev);
3666 if (!adev->platform) {
3667 free(adev->snd_dev_ref_cnt);
3668 free(adev);
3669 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3670 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003671 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003672 return -EINVAL;
3673 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003674
Naresh Tanniru4c630392014-05-12 01:05:52 +05303675 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3676
Eric Laurentc4aef752013-09-12 17:45:53 -07003677 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3678 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3679 if (adev->visualizer_lib == NULL) {
3680 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3681 } else {
3682 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3683 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003684 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003685 "visualizer_hal_start_output");
3686 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003687 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003688 "visualizer_hal_stop_output");
3689 }
3690 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003691 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003692 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003693
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003694 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3695 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3696 if (adev->offload_effects_lib == NULL) {
3697 ALOGE("%s: DLOPEN failed for %s", __func__,
3698 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3699 } else {
3700 ALOGV("%s: DLOPEN successful for %s", __func__,
3701 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3702 adev->offload_effects_start_output =
3703 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3704 "offload_effects_bundle_hal_start_output");
3705 adev->offload_effects_stop_output =
3706 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3707 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003708 adev->offload_effects_set_hpx_state =
3709 (int (*)(bool))dlsym(adev->offload_effects_lib,
3710 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003711 }
3712 }
3713
Mingming Yin514a8bc2014-07-29 15:22:21 -07003714 adev->bt_wb_speech_enabled = false;
3715
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003716 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 *device = &adev->device.common;
3718
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003719 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3720 &adev->streams_output_cfg_list);
3721
Kiran Kandi910e1862013-10-29 13:29:42 -07003722 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003723
3724 char value[PROPERTY_VALUE_MAX];
3725 int trial;
3726 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3727 trial = atoi(value);
3728 if (period_size_is_plausible_for_low_latency(trial)) {
3729 pcm_config_low_latency.period_size = trial;
3730 pcm_config_low_latency.start_threshold = trial / 4;
3731 pcm_config_low_latency.avail_min = trial / 4;
3732 configured_low_latency_capture_period_size = trial;
3733 }
3734 }
3735 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3736 trial = atoi(value);
3737 if (period_size_is_plausible_for_low_latency(trial)) {
3738 configured_low_latency_capture_period_size = trial;
3739 }
3740 }
3741
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003742 pthread_mutex_unlock(&adev_init_lock);
3743
Eric Laurent994a6932013-07-17 11:51:42 -07003744 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 return 0;
3746}
3747
3748static struct hw_module_methods_t hal_module_methods = {
3749 .open = adev_open,
3750};
3751
3752struct audio_module HAL_MODULE_INFO_SYM = {
3753 .common = {
3754 .tag = HARDWARE_MODULE_TAG,
3755 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3756 .hal_api_version = HARDWARE_HAL_API_VERSION,
3757 .id = AUDIO_HARDWARE_MODULE_ID,
3758 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003759 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 .methods = &hal_module_methods,
3761 },
3762};