blob: 1a55750564cdc4eed042ff14740bcf6e4701134f [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200572 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700573 audio_extn_sound_trigger_update_device_status(snd_device,
574 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530575 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800576 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 return 0;
580}
581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582static void check_usecases_codec_backend(struct audio_device *adev,
583 struct audio_usecase *uc_info,
584 snd_device_t snd_device)
585{
586 struct listnode *node;
587 struct audio_usecase *usecase;
588 bool switch_device[AUDIO_USECASE_MAX];
589 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530590 int backend_idx = DEFAULT_CODEC_BACKEND;
591 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592
593 /*
594 * This function is to make sure that all the usecases that are active on
595 * the hardware codec backend are always routed to any one device that is
596 * handled by the hardware codec.
597 * For example, if low-latency and deep-buffer usecases are currently active
598 * on speaker and out_set_parameters(headset) is received on low-latency
599 * output, then we have to make sure deep-buffer is also switched to headset,
600 * because of the limitation that both the devices cannot be enabled
601 * at the same time as they share the same backend.
602 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700603 /*
604 * This call is to check if we need to force routing for a particular stream
605 * If there is a backend configuration change for the device when a
606 * new stream starts, then ADM needs to be closed and re-opened with the new
607 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530608 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700609 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530610 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
611 snd_device);
612 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800614 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800615 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 for (i = 0; i < AUDIO_USECASE_MAX; i++)
617 switch_device[i] = false;
618
619 list_for_each(node, &adev->usecase_list) {
620 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530621
622 if (usecase == uc_info)
623 continue;
624 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
625 ALOGV("%s: backend_idx: %d,"
626 "usecase_backend_idx: %d, curr device: %s, usecase device:"
627 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530628 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530629
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800630 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700631 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
633 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530634 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700636 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700637 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 switch_device[usecase->id] = true;
639 num_uc_to_switch++;
640 }
641 }
642
643 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700644 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530646 /* Make sure the previous devices to be disabled first and then enable the
647 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 list_for_each(node, &adev->usecase_list) {
649 usecase = node_to_item(node, struct audio_usecase, list);
650 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700651 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 }
653 }
654
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700655 list_for_each(node, &adev->usecase_list) {
656 usecase = node_to_item(node, struct audio_usecase, list);
657 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700658 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700659 }
660 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 /* Re-route all the usecases on the shared backend other than the
663 specified usecase to new snd devices */
664 list_for_each(node, &adev->usecase_list) {
665 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530666 /* Update the out_snd_device only for the usecases that are enabled here */
667 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
668 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530669 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 }
673}
674
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700675static void check_and_route_capture_usecases(struct audio_device *adev,
676 struct audio_usecase *uc_info,
677 snd_device_t snd_device)
678{
679 struct listnode *node;
680 struct audio_usecase *usecase;
681 bool switch_device[AUDIO_USECASE_MAX];
682 int i, num_uc_to_switch = 0;
683
684 /*
685 * This function is to make sure that all the active capture usecases
686 * are always routed to the same input sound device.
687 * For example, if audio-record and voice-call usecases are currently
688 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
689 * is received for voice call then we have to make sure that audio-record
690 * usecase is also switched to earpiece i.e. voice-dmic-ef,
691 * because of the limitation that two devices cannot be enabled
692 * at the same time if they share the same backend.
693 */
694 for (i = 0; i < AUDIO_USECASE_MAX; i++)
695 switch_device[i] = false;
696
697 list_for_each(node, &adev->usecase_list) {
698 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800699 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700701 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700702 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
703 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700704 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700705 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
706 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700707 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700708 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700709 switch_device[usecase->id] = true;
710 num_uc_to_switch++;
711 }
712 }
713
714 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700715 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700716
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530717 /* Make sure the previous devices to be disabled first and then enable the
718 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719 list_for_each(node, &adev->usecase_list) {
720 usecase = node_to_item(node, struct audio_usecase, list);
721 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700722 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800723 }
724 }
725
726 list_for_each(node, &adev->usecase_list) {
727 usecase = node_to_item(node, struct audio_usecase, list);
728 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700729 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700730 }
731 }
732
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 /* Re-route all the usecases on the shared backend other than the
734 specified usecase to new snd devices */
735 list_for_each(node, &adev->usecase_list) {
736 usecase = node_to_item(node, struct audio_usecase, list);
737 /* Update the in_snd_device only before enabling the audio route */
738 if (switch_device[usecase->id] ) {
739 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800740 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530741 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 }
743 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744 }
745}
746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700748static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700750 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700751 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752
753 switch (channels) {
754 /*
755 * Do not handle stereo output in Multi-channel cases
756 * Stereo case is handled in normal playback path
757 */
758 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700759 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
760 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
761 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765 break;
766 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700767 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774 break;
775 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700776 ALOGE("HDMI does not support multi channel playback");
777 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778 break;
779 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700780 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781}
782
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800783audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
784 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700785{
786 struct audio_usecase *usecase;
787 struct listnode *node;
788
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800791 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700792 ALOGV("%s: usecase id %d", __func__, usecase->id);
793 return usecase->id;
794 }
795 }
796 return USECASE_INVALID;
797}
798
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700799struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700800 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700801{
802 struct audio_usecase *usecase;
803 struct listnode *node;
804
805 list_for_each(node, &adev->usecase_list) {
806 usecase = node_to_item(node, struct audio_usecase, list);
807 if (usecase->id == uc_id)
808 return usecase;
809 }
810 return NULL;
811}
812
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700813int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800815 snd_device_t out_snd_device = SND_DEVICE_NONE;
816 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 struct audio_usecase *usecase = NULL;
818 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800819 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800820 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800821 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800822 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 usecase = get_usecase_from_list(adev, uc_id);
826 if (usecase == NULL) {
827 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
828 return -EINVAL;
829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800831 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800832 (usecase->type == VOIP_CALL) ||
833 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700834 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800835 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700836 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 usecase->devices = usecase->stream.out->devices;
838 } else {
839 /*
840 * If the voice call is active, use the sound devices of voice call usecase
841 * so that it would not result any device switch. All the usecases will
842 * be switched to new device when select_devices() is called for voice call
843 * usecase. This is to avoid switching devices for voice call when
844 * check_usecases_codec_backend() is called below.
845 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700846 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800848 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700849 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
850 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 in_snd_device = vc_usecase->in_snd_device;
852 out_snd_device = vc_usecase->out_snd_device;
853 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 } else if (voice_extn_compress_voip_is_active(adev)) {
855 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700856 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530857 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700858 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800859 in_snd_device = voip_usecase->in_snd_device;
860 out_snd_device = voip_usecase->out_snd_device;
861 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800862 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800863 hfp_ucid = audio_extn_hfp_get_usecase();
864 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700865 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800866 in_snd_device = hfp_usecase->in_snd_device;
867 out_snd_device = hfp_usecase->out_snd_device;
868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 }
870 if (usecase->type == PCM_PLAYBACK) {
871 usecase->devices = usecase->stream.out->devices;
872 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700873 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800875 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700876 if (usecase->stream.out == adev->primary_output &&
877 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800878 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700879 select_devices(adev, adev->active_input->usecase);
880 }
881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 } else if (usecase->type == PCM_CAPTURE) {
883 usecase->devices = usecase->stream.in->device;
884 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700885 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530887 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
888 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
889 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
890 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800892 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700893 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
894 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700895 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
901 if (out_snd_device == usecase->out_snd_device &&
902 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800903 return 0;
904 }
905
sangwoobc677242013-08-08 16:53:43 +0900906 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700907 out_snd_device, platform_get_snd_device_name(out_snd_device),
908 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800910 /*
911 * Limitation: While in call, to do a device switch we need to disable
912 * and enable both RX and TX devices though one of them is same as current
913 * device.
914 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700915 if ((usecase->type == VOICE_CALL) &&
916 (usecase->in_snd_device != SND_DEVICE_NONE) &&
917 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700918 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700919 /* Disable sidetone only if voice call already exists */
920 if (voice_is_call_state_active(adev))
921 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800922 }
923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924 /* Disable current sound devices */
925 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700926 disable_audio_route(adev, usecase);
927 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 }
929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700930 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700931 disable_audio_route(adev, usecase);
932 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 }
934
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800935 /* Applicable only on the targets that has external modem.
936 * New device information should be sent to modem before enabling
937 * the devices to reduce in-call device switch time.
938 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700939 if ((usecase->type == VOICE_CALL) &&
940 (usecase->in_snd_device != SND_DEVICE_NONE) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800942 status = platform_switch_voice_call_enable_device_config(adev->platform,
943 out_snd_device,
944 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700945 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800946
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 /* Enable new sound devices */
948 if (out_snd_device != SND_DEVICE_NONE) {
949 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
950 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700951 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700954 if (in_snd_device != SND_DEVICE_NONE) {
955 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700956 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958
Avinash Vaish71a8b972014-07-24 15:36:33 +0530959 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700960 status = platform_switch_voice_call_device_post(adev->platform,
961 out_snd_device,
962 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530963 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700964 /* Enable sidetone only if voice call already exists */
965 if (voice_is_call_state_active(adev))
966 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530967 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800968
sangwoo170731f2013-06-08 15:36:36 +0900969 usecase->in_snd_device = in_snd_device;
970 usecase->out_snd_device = out_snd_device;
971
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700973 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530974 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700975 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530976 usecase->stream.out->flags,
977 usecase->stream.out->format,
978 usecase->stream.out->sample_rate,
979 usecase->stream.out->bit_width,
980 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700981 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530982 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700983
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900985
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800986 /* Applicable only on the targets that has external modem.
987 * Enable device command should be sent to modem only after
988 * enabling voice call mixer controls
989 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700990 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800991 status = platform_switch_voice_call_usecase_route_post(adev->platform,
992 out_snd_device,
993 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530994 ALOGD("%s: done",__func__);
995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996 return status;
997}
998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999static int stop_input_stream(struct stream_in *in)
1000{
1001 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 struct audio_usecase *uc_info;
1003 struct audio_device *adev = in->dev;
1004
Eric Laurentc8400632013-02-14 19:04:54 -08001005 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006
Eric Laurent994a6932013-07-17 11:51:42 -07001007 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001009 uc_info = get_usecase_from_list(adev, in->usecase);
1010 if (uc_info == NULL) {
1011 ALOGE("%s: Could not find the usecase (%d) in the list",
1012 __func__, in->usecase);
1013 return -EINVAL;
1014 }
1015
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001016 /* Close in-call recording streams */
1017 voice_check_and_stop_incall_rec_usecase(adev, in);
1018
Eric Laurent150dbfe2013-02-27 14:31:02 -08001019 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001020 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021
1022 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001023 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001025 list_remove(&uc_info->list);
1026 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
Eric Laurent994a6932013-07-17 11:51:42 -07001028 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 return ret;
1030}
1031
1032int start_input_stream(struct stream_in *in)
1033{
1034 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001035 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 struct audio_usecase *uc_info;
1037 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301038 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Mingming Yine62d7842013-10-25 16:26:03 -07001040 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301041 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1042 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001043
Naresh Tanniru80659832014-06-04 18:17:56 +05301044
1045 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301046 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301047 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301048 goto error_config;
1049 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301050
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001051 /* Check if source matches incall recording usecase criteria */
1052 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1053 if (ret)
1054 goto error_config;
1055 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001056 ALOGD("%s: Updated usecase(%d: %s)",
1057 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001058
Eric Laurentb23d5282013-05-14 15:27:20 -07001059 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 if (in->pcm_device_id < 0) {
1061 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1062 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001063 ret = -EINVAL;
1064 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066
1067 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001069
1070 if (!uc_info) {
1071 ret = -ENOMEM;
1072 goto error_config;
1073 }
1074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 uc_info->id = in->usecase;
1076 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001077 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 uc_info->devices = in->device;
1079 uc_info->in_snd_device = SND_DEVICE_NONE;
1080 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001082 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301083 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085
Eric Laurentc8400632013-02-14 19:04:54 -08001086 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001087 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1088
1089 unsigned int flags = PCM_IN;
1090 unsigned int pcm_open_retry_count = 0;
1091
1092 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1093 flags |= PCM_MMAP | PCM_NOIRQ;
1094 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1095 }
1096
1097 while (1) {
1098 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1099 flags, &in->config);
1100 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1101 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1102 if (in->pcm != NULL) {
1103 pcm_close(in->pcm);
1104 in->pcm = NULL;
1105 }
1106 if (pcm_open_retry_count-- == 0) {
1107 ret = -EIO;
1108 goto error_open;
1109 }
1110 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1111 continue;
1112 }
1113 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301115 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301116
Eric Laurent994a6932013-07-17 11:51:42 -07001117 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001118 return ret;
1119
1120error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301122 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001123
1124error_config:
1125 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001127
1128 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129}
1130
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001131/* must be called with out->lock locked */
1132static int send_offload_cmd_l(struct stream_out* out, int command)
1133{
1134 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1135
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001136 if (!cmd) {
1137 ALOGE("failed to allocate mem for command 0x%x", command);
1138 return -ENOMEM;
1139 }
1140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001141 ALOGVV("%s %d", __func__, command);
1142
1143 cmd->cmd = command;
1144 list_add_tail(&out->offload_cmd_list, &cmd->node);
1145 pthread_cond_signal(&out->offload_cond);
1146 return 0;
1147}
1148
1149/* must be called iwth out->lock locked */
1150static void stop_compressed_output_l(struct stream_out *out)
1151{
1152 out->offload_state = OFFLOAD_STATE_IDLE;
1153 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001154 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001155 if (out->compr != NULL) {
1156 compress_stop(out->compr);
1157 while (out->offload_thread_blocked) {
1158 pthread_cond_wait(&out->cond, &out->lock);
1159 }
1160 }
1161}
1162
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001163bool is_offload_usecase(audio_usecase_t uc_id)
1164{
1165 unsigned int i;
1166 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1167 if (uc_id == offload_usecases[i])
1168 return true;
1169 }
1170 return false;
1171}
1172
1173static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1174{
1175 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1176 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1177 char value[PROPERTY_VALUE_MAX] = {0};
1178
1179 property_get("audio.offload.multiple.enabled", value, NULL);
1180 if (!(atoi(value) || !strncmp("true", value, 4)))
1181 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1182
1183 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1184 for (i = 0; i < num_usecase; i++) {
1185 if (!(adev->offload_usecases_state & (0x1<<i))) {
1186 adev->offload_usecases_state |= 0x1 << i;
1187 ret = offload_usecases[i];
1188 break;
1189 }
1190 }
1191 ALOGV("%s: offload usecase is %d", __func__, ret);
1192 return ret;
1193}
1194
1195static void free_offload_usecase(struct audio_device *adev,
1196 audio_usecase_t uc_id)
1197{
1198 unsigned int i;
1199 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1200 if (offload_usecases[i] == uc_id) {
1201 adev->offload_usecases_state &= ~(0x1<<i);
1202 break;
1203 }
1204 }
1205 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1206}
1207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001208static void *offload_thread_loop(void *context)
1209{
1210 struct stream_out *out = (struct stream_out *) context;
1211 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001212 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001213
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1215 set_sched_policy(0, SP_FOREGROUND);
1216 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1217
1218 ALOGV("%s", __func__);
1219 pthread_mutex_lock(&out->lock);
1220 for (;;) {
1221 struct offload_cmd *cmd = NULL;
1222 stream_callback_event_t event;
1223 bool send_callback = false;
1224
1225 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1226 __func__, list_empty(&out->offload_cmd_list),
1227 out->offload_state);
1228 if (list_empty(&out->offload_cmd_list)) {
1229 ALOGV("%s SLEEPING", __func__);
1230 pthread_cond_wait(&out->offload_cond, &out->lock);
1231 ALOGV("%s RUNNING", __func__);
1232 continue;
1233 }
1234
1235 item = list_head(&out->offload_cmd_list);
1236 cmd = node_to_item(item, struct offload_cmd, node);
1237 list_remove(item);
1238
1239 ALOGVV("%s STATE %d CMD %d out->compr %p",
1240 __func__, out->offload_state, cmd->cmd, out->compr);
1241
1242 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1243 free(cmd);
1244 break;
1245 }
1246
1247 if (out->compr == NULL) {
1248 ALOGE("%s: Compress handle is NULL", __func__);
1249 pthread_cond_signal(&out->cond);
1250 continue;
1251 }
1252 out->offload_thread_blocked = true;
1253 pthread_mutex_unlock(&out->lock);
1254 send_callback = false;
1255 switch(cmd->cmd) {
1256 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001257 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001258 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001259 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260 send_callback = true;
1261 event = STREAM_CBK_EVENT_WRITE_READY;
1262 break;
1263 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001264 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301265 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001266 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301267 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001268 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301269 if (ret < 0)
1270 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301271 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301272 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001273 compress_drain(out->compr);
1274 else
1275 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301276 if (ret != -ENETRESET) {
1277 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301278 pthread_mutex_lock(&out->lock);
1279 out->send_new_metadata = 1;
1280 out->send_next_track_params = true;
1281 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301282 event = STREAM_CBK_EVENT_DRAIN_READY;
1283 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1284 } else
1285 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001286 break;
1287 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001290 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001291 send_callback = true;
1292 event = STREAM_CBK_EVENT_DRAIN_READY;
1293 break;
1294 default:
1295 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1296 break;
1297 }
1298 pthread_mutex_lock(&out->lock);
1299 out->offload_thread_blocked = false;
1300 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001301 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001302 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001304 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 free(cmd);
1306 }
1307
1308 pthread_cond_signal(&out->cond);
1309 while (!list_empty(&out->offload_cmd_list)) {
1310 item = list_head(&out->offload_cmd_list);
1311 list_remove(item);
1312 free(node_to_item(item, struct offload_cmd, node));
1313 }
1314 pthread_mutex_unlock(&out->lock);
1315
1316 return NULL;
1317}
1318
1319static int create_offload_callback_thread(struct stream_out *out)
1320{
1321 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1322 list_init(&out->offload_cmd_list);
1323 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1324 offload_thread_loop, out);
1325 return 0;
1326}
1327
1328static int destroy_offload_callback_thread(struct stream_out *out)
1329{
1330 pthread_mutex_lock(&out->lock);
1331 stop_compressed_output_l(out);
1332 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1333
1334 pthread_mutex_unlock(&out->lock);
1335 pthread_join(out->offload_thread, (void **) NULL);
1336 pthread_cond_destroy(&out->offload_cond);
1337
1338 return 0;
1339}
1340
Eric Laurent07eeafd2013-10-06 12:52:49 -07001341static bool allow_hdmi_channel_config(struct audio_device *adev)
1342{
1343 struct listnode *node;
1344 struct audio_usecase *usecase;
1345 bool ret = true;
1346
1347 list_for_each(node, &adev->usecase_list) {
1348 usecase = node_to_item(node, struct audio_usecase, list);
1349 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1350 /*
1351 * If voice call is already existing, do not proceed further to avoid
1352 * disabling/enabling both RX and TX devices, CSD calls, etc.
1353 * Once the voice call done, the HDMI channels can be configured to
1354 * max channels of remaining use cases.
1355 */
1356 if (usecase->id == USECASE_VOICE_CALL) {
1357 ALOGD("%s: voice call is active, no change in HDMI channels",
1358 __func__);
1359 ret = false;
1360 break;
1361 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1362 ALOGD("%s: multi channel playback is active, "
1363 "no change in HDMI channels", __func__);
1364 ret = false;
1365 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001366 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001367 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001368 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1369 ", no change in HDMI channels", __func__,
1370 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001371 ret = false;
1372 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001373 }
1374 }
1375 }
1376 return ret;
1377}
1378
1379static int check_and_set_hdmi_channels(struct audio_device *adev,
1380 unsigned int channels)
1381{
1382 struct listnode *node;
1383 struct audio_usecase *usecase;
1384
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001385 unsigned int supported_channels = platform_edid_get_max_channels(
1386 adev->platform);
1387 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 /* Check if change in HDMI channel config is allowed */
1389 if (!allow_hdmi_channel_config(adev))
1390 return 0;
1391
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001392 if (channels > supported_channels)
1393 channels = supported_channels;
1394
Eric Laurent07eeafd2013-10-06 12:52:49 -07001395 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001396 ALOGD("%s: Requested channels are same as current channels(%d)",
1397 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001398 return 0;
1399 }
1400
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001401 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001403 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001404 adev->cur_hdmi_channels = channels;
1405
1406 /*
1407 * Deroute all the playback streams routed to HDMI so that
1408 * the back end is deactivated. Note that backend will not
1409 * be deactivated if any one stream is connected to it.
1410 */
1411 list_for_each(node, &adev->usecase_list) {
1412 usecase = node_to_item(node, struct audio_usecase, list);
1413 if (usecase->type == PCM_PLAYBACK &&
1414 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001415 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 }
1417 }
1418
1419 /*
1420 * Enable all the streams disabled above. Now the HDMI backend
1421 * will be activated with new channel configuration
1422 */
1423 list_for_each(node, &adev->usecase_list) {
1424 usecase = node_to_item(node, struct audio_usecase, list);
1425 if (usecase->type == PCM_PLAYBACK &&
1426 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001427 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428 }
1429 }
1430
1431 return 0;
1432}
1433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434static int stop_output_stream(struct stream_out *out)
1435{
1436 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 struct audio_usecase *uc_info;
1438 struct audio_device *adev = out->dev;
1439
Eric Laurent994a6932013-07-17 11:51:42 -07001440 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 uc_info = get_usecase_from_list(adev, out->usecase);
1443 if (uc_info == NULL) {
1444 ALOGE("%s: Could not find the usecase (%d) in the list",
1445 __func__, out->usecase);
1446 return -EINVAL;
1447 }
1448
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001449 if (is_offload_usecase(out->usecase) &&
1450 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001451 if (adev->visualizer_stop_output != NULL)
1452 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001453
1454 audio_extn_dts_remove_state_notifier_node(out->usecase);
1455
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001456 if (adev->offload_effects_stop_output != NULL)
1457 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1458 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001459
Eric Laurent150dbfe2013-02-27 14:31:02 -08001460 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001461 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462
1463 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001464 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001466 list_remove(&uc_info->list);
1467 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001469 if (is_offload_usecase(out->usecase) &&
1470 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1471 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1472 ALOGV("Disable passthrough , reset mixer to pcm");
1473 /* NO_PASSTHROUGH */
1474 out->compr_config.codec->compr_passthr = 0;
1475 audio_extn_dolby_set_hdmi_config(adev, out);
1476 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1477 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001478 /* Must be called after removing the usecase from list */
1479 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1480 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1481
Eric Laurent994a6932013-07-17 11:51:42 -07001482 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 return ret;
1484}
1485
1486int start_output_stream(struct stream_out *out)
1487{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001489 int sink_channels = 0;
1490 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 struct audio_usecase *uc_info;
1492 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301493 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001495 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1496 ret = -EINVAL;
1497 goto error_config;
1498 }
1499
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301500 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1501 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1502 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301503
Naresh Tanniru80659832014-06-04 18:17:56 +05301504 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301505 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301506 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301507 goto error_config;
1508 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301509
Eric Laurentb23d5282013-05-14 15:27:20 -07001510 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 if (out->pcm_device_id < 0) {
1512 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1513 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001514 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001515 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516 }
1517
1518 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001519
1520 if (!uc_info) {
1521 ret = -ENOMEM;
1522 goto error_config;
1523 }
1524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 uc_info->id = out->usecase;
1526 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001527 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 uc_info->devices = out->devices;
1529 uc_info->in_snd_device = SND_DEVICE_NONE;
1530 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001531 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001532 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001533 if (is_offload_usecase(out->usecase)) {
1534 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001535 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1536 }
1537 }
Mingming Yin9c041392014-05-01 15:37:31 -07001538 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1539 if (!strncmp("true", prop_value, 4)) {
1540 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001541 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1542 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001543 check_and_set_hdmi_channels(adev, sink_channels);
1544 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001545 if (is_offload_usecase(out->usecase)) {
1546 unsigned int ch_count = out->compr_config.codec->ch_in;
1547 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1548 /* backend channel config for passthrough stream is stereo */
1549 ch_count = 2;
1550 check_and_set_hdmi_channels(adev, ch_count);
1551 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001552 check_and_set_hdmi_channels(adev, out->config.channels);
1553 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001554 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001555 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001556 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 select_devices(adev, out->usecase);
1559
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001560 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1561 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001562 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001563 unsigned int flags = PCM_OUT;
1564 unsigned int pcm_open_retry_count = 0;
1565 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1566 flags |= PCM_MMAP | PCM_NOIRQ;
1567 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1568 } else
1569 flags |= PCM_MONOTONIC;
1570
1571 while (1) {
1572 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1573 flags, &out->config);
1574 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1575 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1576 if (out->pcm != NULL) {
1577 pcm_close(out->pcm);
1578 out->pcm = NULL;
1579 }
1580 if (pcm_open_retry_count-- == 0) {
1581 ret = -EIO;
1582 goto error_open;
1583 }
1584 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1585 continue;
1586 }
1587 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001588 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001589 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1590 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001592 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1593 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001594 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001595 out->compr = compress_open(adev->snd_card,
1596 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001597 COMPRESS_IN, &out->compr_config);
1598 if (out->compr && !is_compress_ready(out->compr)) {
1599 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1600 compress_close(out->compr);
1601 out->compr = NULL;
1602 ret = -EIO;
1603 goto error_open;
1604 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301605 /* compress_open sends params of the track, so reset the flag here */
1606 out->is_compr_metadata_avail = false;
1607
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001608 if (out->offload_callback)
1609 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001610
Fred Oh3f43e742015-03-04 18:42:34 -08001611 /* Since small bufs uses blocking writes, a write will be blocked
1612 for the default max poll time (20s) in the event of an SSR.
1613 Reduce the poll time to observe and deal with SSR faster.
1614 */
1615 if (out->use_small_bufs) {
1616 compress_set_max_poll_wait(out->compr, 1000);
1617 }
1618
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001619 audio_extn_dts_create_state_notifier_node(out->usecase);
1620 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1621 popcount(out->channel_mask),
1622 out->playback_started);
1623
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001624#ifdef DS1_DOLBY_DDP_ENABLED
1625 if (audio_extn_is_dolby_format(out->format))
1626 audio_extn_dolby_send_ddp_endp_params(adev);
1627#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001628 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1629 if (adev->visualizer_start_output != NULL)
1630 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1631 if (adev->offload_effects_start_output != NULL)
1632 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001633 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 }
Eric Laurent994a6932013-07-17 11:51:42 -07001636 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001638error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001640error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001641 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642}
1643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644static int check_input_parameters(uint32_t sample_rate,
1645 audio_format_t format,
1646 int channel_count)
1647{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001648 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001650 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001651 !voice_extn_compress_voip_is_format_supported(format) &&
1652 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001653
1654 switch (channel_count) {
1655 case 1:
1656 case 2:
1657 case 6:
1658 break;
1659 default:
1660 ret = -EINVAL;
1661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
1663 switch (sample_rate) {
1664 case 8000:
1665 case 11025:
1666 case 12000:
1667 case 16000:
1668 case 22050:
1669 case 24000:
1670 case 32000:
1671 case 44100:
1672 case 48000:
1673 break;
1674 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001675 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 }
1677
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001678 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679}
1680
1681static size_t get_input_buffer_size(uint32_t sample_rate,
1682 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001683 int channel_count,
1684 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685{
1686 size_t size = 0;
1687
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001688 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1689 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001691 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001692 if (is_low_latency)
1693 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001694 /* ToDo: should use frame_size computed based on the format and
1695 channel_count here. */
1696 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001698 /* make sure the size is multiple of 32 bytes
1699 * At 48 kHz mono 16-bit PCM:
1700 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1701 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1702 */
1703 size += 0x1f;
1704 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001705
1706 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707}
1708
1709static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1710{
1711 struct stream_out *out = (struct stream_out *)stream;
1712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714}
1715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001716static int out_set_sample_rate(struct audio_stream *stream __unused,
1717 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718{
1719 return -ENOSYS;
1720}
1721
1722static size_t out_get_buffer_size(const struct audio_stream *stream)
1723{
1724 struct stream_out *out = (struct stream_out *)stream;
1725
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001728 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1729 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001731 return out->config.period_size *
1732 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733}
1734
1735static uint32_t out_get_channels(const struct audio_stream *stream)
1736{
1737 struct stream_out *out = (struct stream_out *)stream;
1738
1739 return out->channel_mask;
1740}
1741
1742static audio_format_t out_get_format(const struct audio_stream *stream)
1743{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744 struct stream_out *out = (struct stream_out *)stream;
1745
1746 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747}
1748
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001749static int out_set_format(struct audio_stream *stream __unused,
1750 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751{
1752 return -ENOSYS;
1753}
1754
1755static int out_standby(struct audio_stream *stream)
1756{
1757 struct stream_out *out = (struct stream_out *)stream;
1758 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301760 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1761 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1763 /* Ignore standby in case of voip call because the voip output
1764 * stream is closed in adev_close_output_stream()
1765 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301766 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001767 return 0;
1768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001774 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 if (out->pcm) {
1776 pcm_close(out->pcm);
1777 out->pcm = NULL;
1778 }
1779 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001780 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301782 out->send_next_track_params = false;
1783 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001784 out->gapless_mdata.encoder_delay = 0;
1785 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 if (out->compr != NULL) {
1787 compress_close(out->compr);
1788 out->compr = NULL;
1789 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001792 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 }
1794 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001795 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 return 0;
1797}
1798
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001799static int out_dump(const struct audio_stream *stream __unused,
1800 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801{
1802 return 0;
1803}
1804
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1806{
1807 int ret = 0;
1808 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001809
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001810 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001811 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812 return -EINVAL;
1813 }
1814
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001815 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1816 if (ret >= 0) {
1817 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1818 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1819 ALOGV("ADTS format is set in offload mode");
1820 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001821 }
1822
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301823 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001824
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001825 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1826 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301827 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001828 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1830 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301831 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 }
1833
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 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
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302119 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2120 setChannelStatus(out, buffer, bytes);
2121 adev->mChannelStatusSet = true;
2122 }
2123
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002124 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002125 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002127 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2129 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302130 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2131 ALOGD("copl(%p):send next track params in gapless", out);
2132 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2133 out->send_next_track_params = false;
2134 out->is_compr_metadata_avail = false;
2135 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002136 }
2137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302139 if (ret < 0)
2140 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002141 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002142 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302143 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302145 } else if (-ENETRESET == ret) {
2146 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2147 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2148 pthread_mutex_unlock(&out->lock);
2149 out_standby(&out->stream.common);
2150 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302152 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002154 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 out->playback_started = 1;
2156 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002157
2158 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2159 popcount(out->channel_mask),
2160 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 }
2162 pthread_mutex_unlock(&out->lock);
2163 return ret;
2164 } else {
2165 if (out->pcm) {
2166 if (out->muted)
2167 memset((void *)buffer, 0, bytes);
2168 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002169 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2170 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2171 else
2172 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302173 if (ret < 0)
2174 ret = -errno;
2175 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002176 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 }
2179
2180exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302181 /* ToDo: There may be a corner case when SSR happens back to back during
2182 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302183 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302184 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302185 }
2186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 pthread_mutex_unlock(&out->lock);
2188
2189 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002190 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002191 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302192 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302193 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302194 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302195 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302196 out->standby = true;
2197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002199 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302200 out_get_sample_rate(&out->stream.common));
2201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 }
2203 return bytes;
2204}
2205
2206static int out_get_render_position(const struct audio_stream_out *stream,
2207 uint32_t *dsp_frames)
2208{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302210 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002211
2212 if (dsp_frames == NULL)
2213 return -EINVAL;
2214
2215 *dsp_frames = 0;
2216 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002217 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 pthread_mutex_lock(&out->lock);
2219 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302222 if (ret < 0)
2223 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 ALOGVV("%s rendered frames %d sample_rate %d",
2225 __func__, *dsp_frames, out->sample_rate);
2226 }
2227 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302228 if (-ENETRESET == ret) {
2229 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2230 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2231 return -EINVAL;
2232 } else if(ret < 0) {
2233 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2234 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302235 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2236 /*
2237 * Handle corner case where compress session is closed during SSR
2238 * and timestamp is queried
2239 */
2240 ALOGE(" ERROR: sound card not active, return error");
2241 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302242 } else {
2243 return 0;
2244 }
Zhou Song32a556e2015-05-05 10:46:56 +08002245 } else if (audio_is_linear_pcm(out->format)) {
2246 *dsp_frames = out->written;
2247 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 } else
2249 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250}
2251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002252static int out_add_audio_effect(const struct audio_stream *stream __unused,
2253 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return 0;
2256}
2257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002258static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2259 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260{
2261 return 0;
2262}
2263
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002264static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2265 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266{
2267 return -EINVAL;
2268}
2269
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002270static int out_get_presentation_position(const struct audio_stream_out *stream,
2271 uint64_t *frames, struct timespec *timestamp)
2272{
2273 struct stream_out *out = (struct stream_out *)stream;
2274 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002275 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002276
2277 pthread_mutex_lock(&out->lock);
2278
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002279 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002280 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302281 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002282 &out->sample_rate);
2283 ALOGVV("%s rendered frames %ld sample_rate %d",
2284 __func__, dsp_frames, out->sample_rate);
2285 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302286 if (ret < 0)
2287 ret = -errno;
2288 if (-ENETRESET == ret) {
2289 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2290 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2291 ret = -EINVAL;
2292 } else
2293 ret = 0;
2294
Eric Laurent949a0892013-09-20 09:20:13 -07002295 /* this is the best we can do */
2296 clock_gettime(CLOCK_MONOTONIC, timestamp);
2297 }
2298 } else {
2299 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002300 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002301 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2302 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002303 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002304 // This adjustment accounts for buffering after app processor.
2305 // It is based on estimated DSP latency per use case, rather than exact.
2306 signed_frames -=
2307 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2308
Eric Laurent949a0892013-09-20 09:20:13 -07002309 // It would be unusual for this value to be negative, but check just in case ...
2310 if (signed_frames >= 0) {
2311 *frames = signed_frames;
2312 ret = 0;
2313 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002314 }
2315 }
2316 }
2317
2318 pthread_mutex_unlock(&out->lock);
2319
2320 return ret;
2321}
2322
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323static int out_set_callback(struct audio_stream_out *stream,
2324 stream_callback_t callback, void *cookie)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327
2328 ALOGV("%s", __func__);
2329 pthread_mutex_lock(&out->lock);
2330 out->offload_callback = callback;
2331 out->offload_cookie = cookie;
2332 pthread_mutex_unlock(&out->lock);
2333 return 0;
2334}
2335
2336static int out_pause(struct audio_stream_out* stream)
2337{
2338 struct stream_out *out = (struct stream_out *)stream;
2339 int status = -ENOSYS;
2340 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002341 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002342 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 pthread_mutex_lock(&out->lock);
2344 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302345 struct audio_device *adev = out->dev;
2346 int snd_scard_state = get_snd_card_state(adev);
2347
2348 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2349 status = compress_pause(out->compr);
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302353 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002354 audio_extn_dts_notify_playback_state(out->usecase, 0,
2355 out->sample_rate, popcount(out->channel_mask),
2356 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 }
2358 pthread_mutex_unlock(&out->lock);
2359 }
2360 return status;
2361}
2362
2363static int out_resume(struct audio_stream_out* stream)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 int status = -ENOSYS;
2367 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002368 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002369 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 status = 0;
2371 pthread_mutex_lock(&out->lock);
2372 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302373 struct audio_device *adev = out->dev;
2374 int snd_scard_state = get_snd_card_state(adev);
2375
2376 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2377 status = compress_resume(out->compr);
2378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002380
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302381 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002382 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2383 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 }
2385 pthread_mutex_unlock(&out->lock);
2386 }
2387 return status;
2388}
2389
2390static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2391{
2392 struct stream_out *out = (struct stream_out *)stream;
2393 int status = -ENOSYS;
2394 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002395 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396 pthread_mutex_lock(&out->lock);
2397 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2398 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2399 else
2400 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2401 pthread_mutex_unlock(&out->lock);
2402 }
2403 return status;
2404}
2405
2406static int out_flush(struct audio_stream_out* stream)
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002410 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002411 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 pthread_mutex_lock(&out->lock);
2413 stop_compressed_output_l(out);
2414 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002415 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 return 0;
2417 }
2418 return -ENOSYS;
2419}
2420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421/** audio_stream_in implementation **/
2422static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2423{
2424 struct stream_in *in = (struct stream_in *)stream;
2425
2426 return in->config.rate;
2427}
2428
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002429static int in_set_sample_rate(struct audio_stream *stream __unused,
2430 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431{
2432 return -ENOSYS;
2433}
2434
2435static size_t in_get_buffer_size(const struct audio_stream *stream)
2436{
2437 struct stream_in *in = (struct stream_in *)stream;
2438
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002439 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2440 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002441 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2442 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002443
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002444 return in->config.period_size *
2445 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446}
2447
2448static uint32_t in_get_channels(const struct audio_stream *stream)
2449{
2450 struct stream_in *in = (struct stream_in *)stream;
2451
2452 return in->channel_mask;
2453}
2454
2455static audio_format_t in_get_format(const struct audio_stream *stream)
2456{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002457 struct stream_in *in = (struct stream_in *)stream;
2458
2459 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460}
2461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002462static int in_set_format(struct audio_stream *stream __unused,
2463 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464{
2465 return -ENOSYS;
2466}
2467
2468static int in_standby(struct audio_stream *stream)
2469{
2470 struct stream_in *in = (struct stream_in *)stream;
2471 struct audio_device *adev = in->dev;
2472 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302473 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2474 stream, in->usecase, use_case_table[in->usecase]);
2475
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002476 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2477 /* Ignore standby in case of voip call because the voip input
2478 * stream is closed in adev_close_input_stream()
2479 */
2480 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2481 return status;
2482 }
2483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002485 if (!in->standby && in->is_st_session) {
2486 ALOGD("%s: sound trigger pcm stop lab", __func__);
2487 audio_extn_sound_trigger_stop_lab(in);
2488 in->standby = 1;
2489 }
2490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002492 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002494 if (in->pcm) {
2495 pcm_close(in->pcm);
2496 in->pcm = NULL;
2497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002499 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 }
2501 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002502 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 return status;
2504}
2505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002506static int in_dump(const struct audio_stream *stream __unused,
2507 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508{
2509 return 0;
2510}
2511
2512static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2513{
2514 struct stream_in *in = (struct stream_in *)stream;
2515 struct audio_device *adev = in->dev;
2516 struct str_parms *parms;
2517 char *str;
2518 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002519 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302521 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 parms = str_parms_create_str(kvpairs);
2523
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302524 if (!parms)
2525 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002527 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002528
2529 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2530 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 val = atoi(value);
2532 /* no audio source uses val == 0 */
2533 if ((in->source != val) && (val != 0)) {
2534 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002535 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2536 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2537 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2538 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002539 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002540 err = voice_extn_compress_voip_open_input_stream(in);
2541 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002542 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002543 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002544 }
2545 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
2547 }
2548
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002549 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2550 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002552 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 in->device = val;
2554 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002555 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002556 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 }
2558 }
2559
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002560done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002562 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563
2564 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302565error:
Eric Laurent994a6932013-07-17 11:51:42 -07002566 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 return ret;
2568}
2569
2570static char* in_get_parameters(const struct audio_stream *stream,
2571 const char *keys)
2572{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002573 struct stream_in *in = (struct stream_in *)stream;
2574 struct str_parms *query = str_parms_create_str(keys);
2575 char *str;
2576 char value[256];
2577 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002578
2579 if (!query || !reply) {
2580 ALOGE("in_get_parameters: failed to create query or reply");
2581 return NULL;
2582 }
2583
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002584 ALOGV("%s: enter: keys - %s", __func__, keys);
2585
2586 voice_extn_in_get_parameters(in, query, reply);
2587
2588 str = str_parms_to_str(reply);
2589 str_parms_destroy(query);
2590 str_parms_destroy(reply);
2591
2592 ALOGV("%s: exit: returns - %s", __func__, str);
2593 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594}
2595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002596static int in_set_gain(struct audio_stream_in *stream __unused,
2597 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598{
2599 return 0;
2600}
2601
2602static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2603 size_t bytes)
2604{
2605 struct stream_in *in = (struct stream_in *)stream;
2606 struct audio_device *adev = in->dev;
2607 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302608 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302611
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002612 if (in->is_st_session) {
2613 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2614 /* Read from sound trigger HAL */
2615 audio_extn_sound_trigger_read(in, buffer, bytes);
2616 pthread_mutex_unlock(&in->lock);
2617 return bytes;
2618 }
2619
2620 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2621 ALOGD(" %s: sound card is not active/SSR state", __func__);
2622 ret= -EIO;;
2623 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 }
2625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002627 pthread_mutex_lock(&adev->lock);
2628 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2629 ret = voice_extn_compress_voip_start_input_stream(in);
2630 else
2631 ret = start_input_stream(in);
2632 pthread_mutex_unlock(&adev->lock);
2633 if (ret != 0) {
2634 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 }
2636 in->standby = 0;
2637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638
2639 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002640 if (audio_extn_ssr_get_enabled() &&
2641 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002642 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002643 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2644 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002645 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2646 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002647 else
2648 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302649 if (ret < 0)
2650 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652
2653 /*
2654 * Instead of writing zeroes here, we could trust the hardware
2655 * to always provide zeroes when muted.
2656 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302657 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2658 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 memset(buffer, 0, bytes);
2660
2661exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302662 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302663 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002664 if (-ENETRESET == ret)
2665 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 pthread_mutex_unlock(&in->lock);
2668
2669 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302670 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302671 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302672 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302673 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302674 in->standby = true;
2675 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302676 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002678 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002679 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302680 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 }
2682 return bytes;
2683}
2684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002685static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686{
2687 return 0;
2688}
2689
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002690static int add_remove_audio_effect(const struct audio_stream *stream,
2691 effect_handle_t effect,
2692 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002694 struct stream_in *in = (struct stream_in *)stream;
2695 int status = 0;
2696 effect_descriptor_t desc;
2697
2698 status = (*effect)->get_descriptor(effect, &desc);
2699 if (status != 0)
2700 return status;
2701
2702 pthread_mutex_lock(&in->lock);
2703 pthread_mutex_lock(&in->dev->lock);
2704 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2705 in->enable_aec != enable &&
2706 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2707 in->enable_aec = enable;
2708 if (!in->standby)
2709 select_devices(in->dev, in->usecase);
2710 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002711 if (in->enable_ns != enable &&
2712 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2713 in->enable_ns = enable;
2714 if (!in->standby)
2715 select_devices(in->dev, in->usecase);
2716 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 pthread_mutex_unlock(&in->dev->lock);
2718 pthread_mutex_unlock(&in->lock);
2719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 return 0;
2721}
2722
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002723static int in_add_audio_effect(const struct audio_stream *stream,
2724 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
Eric Laurent994a6932013-07-17 11:51:42 -07002726 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002727 return add_remove_audio_effect(stream, effect, true);
2728}
2729
2730static int in_remove_audio_effect(const struct audio_stream *stream,
2731 effect_handle_t effect)
2732{
Eric Laurent994a6932013-07-17 11:51:42 -07002733 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002734 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735}
2736
2737static int adev_open_output_stream(struct audio_hw_device *dev,
2738 audio_io_handle_t handle,
2739 audio_devices_t devices,
2740 audio_output_flags_t flags,
2741 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002742 struct audio_stream_out **stream_out,
2743 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744{
2745 struct audio_device *adev = (struct audio_device *)dev;
2746 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002747 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002748 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302751
2752 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2753 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2754 ALOGE(" sound card is not active rejecting compress output open request");
2755 return -EINVAL;
2756 }
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2759
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302760 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2761 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2762 devices, flags, &out->stream);
2763
2764
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002765 if (!out) {
2766 return -ENOMEM;
2767 }
2768
Haynes Mathew George204045b2015-02-25 20:32:03 -08002769 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2770 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 if (devices == AUDIO_DEVICE_NONE)
2773 devices = AUDIO_DEVICE_OUT_SPEAKER;
2774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 out->flags = flags;
2776 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002777 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002778 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002779 out->sample_rate = config->sample_rate;
2780 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2781 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002782 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002783 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002784 out->non_blocking = 0;
2785 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002787 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2788 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002789 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2790 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2791
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002792 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002793 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2794 ret = read_hdmi_channel_masks(out);
2795
2796 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2797 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002798 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002799 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002800 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002801
2802 if (config->sample_rate == 0)
2803 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2804 if (config->channel_mask == 0)
2805 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2806
2807 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2810 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002812 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2815 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002816 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002817 ret = voice_extn_compress_voip_open_output_stream(out);
2818 if (ret != 0) {
2819 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2820 __func__, ret);
2821 goto error_open;
2822 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2824 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2825 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2826 ALOGE("%s: Unsupported Offload information", __func__);
2827 ret = -EINVAL;
2828 goto error_open;
2829 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002830
2831 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2832 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2833 ALOGV("read and update_pass through formats");
2834 ret = audio_extn_dolby_update_passt_formats(adev, out);
2835 if(ret != 0) {
2836 goto error_open;
2837 }
2838 if(config->offload_info.format == 0)
2839 config->offload_info.format = out->supported_formats[0];
2840 }
2841
Mingming Yin90310102013-11-13 16:57:00 -08002842 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002843 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 ALOGE("%s: Unsupported audio format", __func__);
2845 ret = -EINVAL;
2846 goto error_open;
2847 }
2848
2849 out->compr_config.codec = (struct snd_codec *)
2850 calloc(1, sizeof(struct snd_codec));
2851
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002852 if (!out->compr_config.codec) {
2853 ret = -ENOMEM;
2854 goto error_open;
2855 }
2856
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002857 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 if (config->offload_info.channel_mask)
2859 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002860 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002862 config->offload_info.channel_mask = config->channel_mask;
2863 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002864 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 out->sample_rate = config->offload_info.sample_rate;
2866
2867 out->stream.set_callback = out_set_callback;
2868 out->stream.pause = out_pause;
2869 out->stream.resume = out_resume;
2870 out->stream.drain = out_drain;
2871 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002872 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002874 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002875 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002876 audio_extn_dolby_get_snd_codec_id(adev, out,
2877 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002878 else
2879 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002881 if (audio_is_offload_pcm(config->offload_info.format)) {
2882 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002883 platform_get_pcm_offload_buffer_size(&config->offload_info);
2884 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2885 out->compr_config.fragment_size =
2886 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002887 } else {
2888 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002889 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002890 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2892 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002893 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 out->compr_config.codec->bit_rate =
2895 config->offload_info.bit_rate;
2896 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002897 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002899 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002900 /*TODO: Do we need to change it for passthrough */
2901 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902
Mingming Yin3ee55c62014-08-04 14:23:35 -07002903 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2904 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002905 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2906 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002907 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002908 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2909
Mingming Yin3ee55c62014-08-04 14:23:35 -07002910 if (out->bit_width == 24) {
2911 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2912 }
2913
Amit Shekhar6f461b12014-08-01 14:52:58 -07002914 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002915 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2918 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002919
Alexy Josephaa54c872014-12-03 02:46:47 -08002920 if (config->offload_info.use_small_bufs) {
2921 //this flag is set from framework only if its for PCM formats
2922 //no need to check for PCM format again
2923 out->non_blocking = 0;
2924 out->use_small_bufs = true;
2925 ALOGI("Keep write blocking for small buff: non_blockling %d",
2926 out->non_blocking);
2927 }
2928
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002929 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302930 out->send_next_track_params = false;
2931 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002932 out->offload_state = OFFLOAD_STATE_IDLE;
2933 out->playback_started = 0;
2934
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002935 audio_extn_dts_create_state_notifier_node(out->usecase);
2936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002937 create_offload_callback_thread(out);
2938 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2939 __func__, config->offload_info.version,
2940 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002941 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002942 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002943 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2944 ret = voice_check_and_set_incall_music_usecase(adev, out);
2945 if (ret != 0) {
2946 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2947 __func__, ret);
2948 goto error_open;
2949 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002950 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2951 if (config->sample_rate == 0)
2952 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2953 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2954 config->sample_rate != 8000) {
2955 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2956 ret = -EINVAL;
2957 goto error_open;
2958 }
2959 out->sample_rate = config->sample_rate;
2960 out->config.rate = config->sample_rate;
2961 if (config->format == AUDIO_FORMAT_DEFAULT)
2962 config->format = AUDIO_FORMAT_PCM_16_BIT;
2963 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2964 config->format = AUDIO_FORMAT_PCM_16_BIT;
2965 ret = -EINVAL;
2966 goto error_open;
2967 }
2968 out->format = config->format;
2969 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2970 out->config = pcm_config_afe_proxy_playback;
2971 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002972 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002973 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2975 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002976 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002977 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2978 format = AUDIO_FORMAT_PCM_16_BIT;
2979 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2980 out->config = pcm_config_deep_buffer;
2981 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002982 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002983 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002984 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002985 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002986 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002987 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 }
2989
Amit Shekhar1d896042014-10-03 13:16:09 -07002990 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2991 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002992 /* TODO remove this hardcoding and check why width is zero*/
2993 if (out->bit_width == 0)
2994 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002995 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2996 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002997 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302998 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002999 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3000 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3001 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003002 if(adev->primary_output == NULL)
3003 adev->primary_output = out;
3004 else {
3005 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003006 ret = -EEXIST;
3007 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003008 }
3009 }
3010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 /* Check if this usecase is already existing */
3012 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003013 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3014 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003017 ret = -EEXIST;
3018 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 }
3020 pthread_mutex_unlock(&adev->lock);
3021
3022 out->stream.common.get_sample_rate = out_get_sample_rate;
3023 out->stream.common.set_sample_rate = out_set_sample_rate;
3024 out->stream.common.get_buffer_size = out_get_buffer_size;
3025 out->stream.common.get_channels = out_get_channels;
3026 out->stream.common.get_format = out_get_format;
3027 out->stream.common.set_format = out_set_format;
3028 out->stream.common.standby = out_standby;
3029 out->stream.common.dump = out_dump;
3030 out->stream.common.set_parameters = out_set_parameters;
3031 out->stream.common.get_parameters = out_get_parameters;
3032 out->stream.common.add_audio_effect = out_add_audio_effect;
3033 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3034 out->stream.get_latency = out_get_latency;
3035 out->stream.set_volume = out_set_volume;
3036 out->stream.write = out_write;
3037 out->stream.get_render_position = out_get_render_position;
3038 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003039 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003042 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003043 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044
3045 config->format = out->stream.common.get_format(&out->stream.common);
3046 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3047 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3048
3049 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303050 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3051 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003052
3053 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3054 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3055 popcount(out->channel_mask), out->playback_started);
3056
Eric Laurent994a6932013-07-17 11:51:42 -07003057 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003059
3060error_open:
3061 free(out);
3062 *stream_out = NULL;
3063 ALOGD("%s: exit: ret %d", __func__, ret);
3064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065}
3066
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003067static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 struct audio_stream_out *stream)
3069{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 struct stream_out *out = (struct stream_out *)stream;
3071 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003072 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3075
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003076 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303077 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303079 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003080 if(ret != 0)
3081 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3082 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003083 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003084 out_standby(&stream->common);
3085
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003086 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003087 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003089 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 if (out->compr_config.codec != NULL)
3091 free(out->compr_config.codec);
3092 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003093
3094 if (adev->voice_tx_output == out)
3095 adev->voice_tx_output = NULL;
3096
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 pthread_cond_destroy(&out->cond);
3098 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003100 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101}
3102
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003103static void close_compress_sessions(struct audio_device *adev)
3104{
Mingming Yin7b762e72015-03-04 13:47:32 -08003105 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303106 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003107 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003108 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303109
3110 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003111 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303112 if (is_offload_usecase(usecase->id)) {
3113 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003114 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3115 out = usecase->stream.out;
3116 pthread_mutex_unlock(&adev->lock);
3117 out_standby(&out->stream.common);
3118 pthread_mutex_lock(&adev->lock);
3119 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303120 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003121 }
3122 pthread_mutex_unlock(&adev->lock);
3123}
3124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3126{
3127 struct audio_device *adev = (struct audio_device *)dev;
3128 struct str_parms *parms;
3129 char *str;
3130 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003131 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003132 int ret;
3133 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003135 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303138 if (!parms)
3139 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003140 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3141 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303142 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303144 struct listnode *node;
3145 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303146 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303147 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003148 //close compress sessions on OFFLINE status
3149 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 } else if (strstr(snd_card_status, "ONLINE")) {
3151 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303152 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303153 if (!platform_is_acdb_initialized(adev->platform)) {
3154 ret = platform_acdb_init(adev->platform);
3155 if(ret)
3156 ALOGE("acdb initialization is failed");
3157
3158 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303159 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303160 }
3161
3162 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003163 status = voice_set_parameters(adev, parms);
3164 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003165 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003167 status = platform_set_parameters(adev->platform, parms);
3168 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003169 goto done;
3170
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3172 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003173 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3175 adev->bluetooth_nrec = true;
3176 else
3177 adev->bluetooth_nrec = false;
3178 }
3179
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3181 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3183 adev->screen_off = false;
3184 else
3185 adev->screen_off = true;
3186 }
3187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003188 ret = str_parms_get_int(parms, "rotation", &val);
3189 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003190 bool reverse_speakers = false;
3191 switch(val) {
3192 // FIXME: note that the code below assumes that the speakers are in the correct placement
3193 // relative to the user when the device is rotated 90deg from its default rotation. This
3194 // assumption is device-specific, not platform-specific like this code.
3195 case 270:
3196 reverse_speakers = true;
3197 break;
3198 case 0:
3199 case 90:
3200 case 180:
3201 break;
3202 default:
3203 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003204 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003205 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 if (status == 0) {
3207 if (adev->speaker_lr_swap != reverse_speakers) {
3208 adev->speaker_lr_swap = reverse_speakers;
3209 // only update the selected device if there is active pcm playback
3210 struct audio_usecase *usecase;
3211 struct listnode *node;
3212 list_for_each(node, &adev->usecase_list) {
3213 usecase = node_to_item(node, struct audio_usecase, list);
3214 if (usecase->type == PCM_PLAYBACK) {
3215 select_devices(adev, usecase->id);
3216 break;
3217 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003218 }
3219 }
3220 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003221 }
3222
Mingming Yin514a8bc2014-07-29 15:22:21 -07003223 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3224 if (ret >= 0) {
3225 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3226 adev->bt_wb_speech_enabled = true;
3227 else
3228 adev->bt_wb_speech_enabled = false;
3229 }
3230
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3232 if (ret >= 0) {
3233 val = atoi(value);
3234 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3235 ALOGV("cache new edid");
3236 platform_cache_edid(adev->platform);
3237 }
3238 }
3239
3240 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3241 if (ret >= 0) {
3242 val = atoi(value);
3243 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3244 ALOGV("invalidate cached edid");
3245 platform_invalidate_edid(adev->platform);
3246 }
3247 }
3248
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003249 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003250
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003251done:
3252 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003253 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303254error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003255 ALOGV("%s: exit with code(%d)", __func__, status);
3256 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257}
3258
3259static char* adev_get_parameters(const struct audio_hw_device *dev,
3260 const char *keys)
3261{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003262 struct audio_device *adev = (struct audio_device *)dev;
3263 struct str_parms *reply = str_parms_create();
3264 struct str_parms *query = str_parms_create_str(keys);
3265 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303266 char value[256] = {0};
3267 int ret = 0;
3268
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003269 if (!query || !reply) {
3270 ALOGE("adev_get_parameters: failed to create query or reply");
3271 return NULL;
3272 }
3273
Naresh Tannirud7205b62014-06-20 02:54:48 +05303274 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3275 sizeof(value));
3276 if (ret >=0) {
3277 int val = 1;
3278 pthread_mutex_lock(&adev->snd_card_status.lock);
3279 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3280 val = 0;
3281 pthread_mutex_unlock(&adev->snd_card_status.lock);
3282 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3283 goto exit;
3284 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003285
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003286 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003287 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003288 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003289 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303290 pthread_mutex_unlock(&adev->lock);
3291
Naresh Tannirud7205b62014-06-20 02:54:48 +05303292exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003293 str = str_parms_to_str(reply);
3294 str_parms_destroy(query);
3295 str_parms_destroy(reply);
3296
3297 ALOGV("%s: exit: returns - %s", __func__, str);
3298 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299}
3300
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003301static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302{
3303 return 0;
3304}
3305
3306static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3307{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003308 int ret;
3309 struct audio_device *adev = (struct audio_device *)dev;
3310 pthread_mutex_lock(&adev->lock);
3311 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003312 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003313 pthread_mutex_unlock(&adev->lock);
3314 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315}
3316
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003317static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3318 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319{
3320 return -ENOSYS;
3321}
3322
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003323static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3324 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325{
3326 return -ENOSYS;
3327}
3328
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003329static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3330 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331{
3332 return -ENOSYS;
3333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3336 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return -ENOSYS;
3339}
3340
3341static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3342{
3343 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 pthread_mutex_lock(&adev->lock);
3346 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003347 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003349 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3350 voice_is_in_call(adev)) {
3351 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303352 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003353 adev->current_call_output = NULL;
3354 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 }
3356 pthread_mutex_unlock(&adev->lock);
3357 return 0;
3358}
3359
3360static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3361{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003362 int ret;
3363
3364 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003365 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003366 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3367 pthread_mutex_unlock(&adev->lock);
3368
3369 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370}
3371
3372static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3373{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003374 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 return 0;
3376}
3377
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003378static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 const struct audio_config *config)
3380{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003381 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003383 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3384 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
3387static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003388 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 audio_devices_t devices,
3390 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003391 struct audio_stream_in **stream_in,
3392 audio_input_flags_t flags __unused,
3393 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003394 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 struct audio_device *adev = (struct audio_device *)dev;
3397 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003398 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003399 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003400 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 *stream_in = NULL;
3403 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3404 return -EINVAL;
3405
3406 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003407
3408 if (!in) {
3409 ALOGE("failed to allocate input stream");
3410 return -ENOMEM;
3411 }
3412
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303413 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003414 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3415 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003417 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 in->stream.common.get_sample_rate = in_get_sample_rate;
3420 in->stream.common.set_sample_rate = in_set_sample_rate;
3421 in->stream.common.get_buffer_size = in_get_buffer_size;
3422 in->stream.common.get_channels = in_get_channels;
3423 in->stream.common.get_format = in_get_format;
3424 in->stream.common.set_format = in_set_format;
3425 in->stream.common.standby = in_standby;
3426 in->stream.common.dump = in_dump;
3427 in->stream.common.set_parameters = in_set_parameters;
3428 in->stream.common.get_parameters = in_get_parameters;
3429 in->stream.common.add_audio_effect = in_add_audio_effect;
3430 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3431 in->stream.set_gain = in_set_gain;
3432 in->stream.read = in_read;
3433 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3434
3435 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003436 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in->standby = 1;
3439 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003440 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441
3442 /* Update config params with the requested sample rate and channels */
3443 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003444 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3445 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3446 is_low_latency = true;
3447#if LOW_LATENCY_CAPTURE_USE_CASE
3448 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3449#endif
3450 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003453 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003455 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303456 if (adev->mode != AUDIO_MODE_IN_CALL) {
3457 ret = -EINVAL;
3458 goto err_open;
3459 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003460 if (config->sample_rate == 0)
3461 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3462 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3463 config->sample_rate != 8000) {
3464 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3465 ret = -EINVAL;
3466 goto err_open;
3467 }
3468 if (config->format == AUDIO_FORMAT_DEFAULT)
3469 config->format = AUDIO_FORMAT_PCM_16_BIT;
3470 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3471 config->format = AUDIO_FORMAT_PCM_16_BIT;
3472 ret = -EINVAL;
3473 goto err_open;
3474 }
3475
3476 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3477 in->config = pcm_config_afe_proxy_record;
3478 in->config.channels = channel_count;
3479 in->config.rate = config->sample_rate;
3480 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003481 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003482 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003483 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3484 ret = -EINVAL;
3485 goto err_open;
3486 }
3487 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003488 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003489 }
Mingming Yine62d7842013-10-25 16:26:03 -07003490 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003491 audio_extn_compr_cap_format_supported(config->format) &&
3492 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003493 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003494 } else {
3495 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003496 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003497 buffer_size = get_input_buffer_size(config->sample_rate,
3498 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003499 channel_count,
3500 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003501 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003502 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3503 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3504 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3505 (in->config.rate == 8000 || in->config.rate == 16000) &&
3506 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3507 voice_extn_compress_voip_open_input_stream(in);
3508 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003511 /* This stream could be for sound trigger lab,
3512 get sound trigger pcm if present */
3513 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303514 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003517 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003518 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
3520err_open:
3521 free(in);
3522 *stream_in = NULL;
3523 return ret;
3524}
3525
3526static void adev_close_input_stream(struct audio_hw_device *dev,
3527 struct audio_stream_in *stream)
3528{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003529 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003530 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003531 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303532
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303533 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003534
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303535 /* Disable echo reference while closing input stream */
3536 platform_set_echo_reference(adev->platform, false);
3537
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003538 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303539 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303541 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003542 if (ret != 0)
3543 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3544 __func__, ret);
3545 } else
3546 in_standby(&stream->common);
3547
Mingming Yin7b762e72015-03-04 13:47:32 -08003548 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003549 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003550 audio_extn_ssr_deinit();
3551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552
Mingming Yine62d7842013-10-25 16:26:03 -07003553 if(audio_extn_compr_cap_enabled() &&
3554 audio_extn_compr_cap_format_supported(in->config.format))
3555 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003556
3557 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 return;
3559}
3560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003561static int adev_dump(const audio_hw_device_t *device __unused,
3562 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
3564 return 0;
3565}
3566
3567static int adev_close(hw_device_t *device)
3568{
3569 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003570
3571 if (!adev)
3572 return 0;
3573
3574 pthread_mutex_lock(&adev_init_lock);
3575
3576 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003577 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003578 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003579 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003580 audio_route_free(adev->audio_route);
3581 free(adev->snd_dev_ref_cnt);
3582 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003583 free(device);
3584 adev = NULL;
3585 }
3586 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 return 0;
3588}
3589
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003590/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3591 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3592 * just that it _might_ work.
3593 */
3594static int period_size_is_plausible_for_low_latency(int period_size)
3595{
3596 switch (period_size) {
3597 case 160:
3598 case 240:
3599 case 320:
3600 case 480:
3601 return 1;
3602 default:
3603 return 0;
3604 }
3605}
3606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607static int adev_open(const hw_module_t *module, const char *name,
3608 hw_device_t **device)
3609{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003610 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003612 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3614
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003615 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003616 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003617 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003618 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003619 ALOGD("%s: returning existing instance of adev", __func__);
3620 ALOGD("%s: exit", __func__);
3621 pthread_mutex_unlock(&adev_init_lock);
3622 return 0;
3623 }
3624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 adev = calloc(1, sizeof(struct audio_device));
3626
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003627 if (!adev) {
3628 pthread_mutex_unlock(&adev_init_lock);
3629 return -ENOMEM;
3630 }
3631
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003632 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3635 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3636 adev->device.common.module = (struct hw_module_t *)module;
3637 adev->device.common.close = adev_close;
3638
3639 adev->device.init_check = adev_init_check;
3640 adev->device.set_voice_volume = adev_set_voice_volume;
3641 adev->device.set_master_volume = adev_set_master_volume;
3642 adev->device.get_master_volume = adev_get_master_volume;
3643 adev->device.set_master_mute = adev_set_master_mute;
3644 adev->device.get_master_mute = adev_get_master_mute;
3645 adev->device.set_mode = adev_set_mode;
3646 adev->device.set_mic_mute = adev_set_mic_mute;
3647 adev->device.get_mic_mute = adev_get_mic_mute;
3648 adev->device.set_parameters = adev_set_parameters;
3649 adev->device.get_parameters = adev_get_parameters;
3650 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3651 adev->device.open_output_stream = adev_open_output_stream;
3652 adev->device.close_output_stream = adev_close_output_stream;
3653 adev->device.open_input_stream = adev_open_input_stream;
3654 adev->device.close_input_stream = adev_close_input_stream;
3655 adev->device.dump = adev_dump;
3656
3657 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003659 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003660 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003663 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003664 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003665 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003666 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003667 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003668 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003669 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303670 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303671
3672 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3673 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003675 adev->platform = platform_init(adev);
3676 if (!adev->platform) {
3677 free(adev->snd_dev_ref_cnt);
3678 free(adev);
3679 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3680 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003681 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003682 return -EINVAL;
3683 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003684
Naresh Tanniru4c630392014-05-12 01:05:52 +05303685 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3686
Eric Laurentc4aef752013-09-12 17:45:53 -07003687 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3688 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3689 if (adev->visualizer_lib == NULL) {
3690 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3691 } else {
3692 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3693 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003694 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003695 "visualizer_hal_start_output");
3696 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003697 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003698 "visualizer_hal_stop_output");
3699 }
3700 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003701 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003702 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003703
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003704 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3705 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3706 if (adev->offload_effects_lib == NULL) {
3707 ALOGE("%s: DLOPEN failed for %s", __func__,
3708 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3709 } else {
3710 ALOGV("%s: DLOPEN successful for %s", __func__,
3711 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3712 adev->offload_effects_start_output =
3713 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3714 "offload_effects_bundle_hal_start_output");
3715 adev->offload_effects_stop_output =
3716 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3717 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003718 adev->offload_effects_set_hpx_state =
3719 (int (*)(bool))dlsym(adev->offload_effects_lib,
3720 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003721 }
3722 }
3723
Mingming Yin514a8bc2014-07-29 15:22:21 -07003724 adev->bt_wb_speech_enabled = false;
3725
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003726 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 *device = &adev->device.common;
3728
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003729 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3730 &adev->streams_output_cfg_list);
3731
Kiran Kandi910e1862013-10-29 13:29:42 -07003732 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003733
3734 char value[PROPERTY_VALUE_MAX];
3735 int trial;
3736 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3737 trial = atoi(value);
3738 if (period_size_is_plausible_for_low_latency(trial)) {
3739 pcm_config_low_latency.period_size = trial;
3740 pcm_config_low_latency.start_threshold = trial / 4;
3741 pcm_config_low_latency.avail_min = trial / 4;
3742 configured_low_latency_capture_period_size = trial;
3743 }
3744 }
3745 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3746 trial = atoi(value);
3747 if (period_size_is_plausible_for_low_latency(trial)) {
3748 configured_low_latency_capture_period_size = trial;
3749 }
3750 }
3751
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003752 pthread_mutex_unlock(&adev_init_lock);
3753
Eric Laurent994a6932013-07-17 11:51:42 -07003754 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 return 0;
3756}
3757
3758static struct hw_module_methods_t hal_module_methods = {
3759 .open = adev_open,
3760};
3761
3762struct audio_module HAL_MODULE_INFO_SYM = {
3763 .common = {
3764 .tag = HARDWARE_MODULE_TAG,
3765 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3766 .hal_api_version = HARDWARE_HAL_API_VERSION,
3767 .id = AUDIO_HARDWARE_MODULE_ID,
3768 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003769 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 .methods = &hal_module_methods,
3771 },
3772};