blob: d738de1f5e856a824609db507dc04f88cca695cb [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) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530703 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
704 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700705 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700706 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
707 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700708 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710 switch_device[usecase->id] = true;
711 num_uc_to_switch++;
712 }
713 }
714
715 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700716 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700717
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530718 /* Make sure the previous devices to be disabled first and then enable the
719 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700720 list_for_each(node, &adev->usecase_list) {
721 usecase = node_to_item(node, struct audio_usecase, list);
722 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700723 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800724 }
725 }
726
727 list_for_each(node, &adev->usecase_list) {
728 usecase = node_to_item(node, struct audio_usecase, list);
729 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700730 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731 }
732 }
733
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734 /* Re-route all the usecases on the shared backend other than the
735 specified usecase to new snd devices */
736 list_for_each(node, &adev->usecase_list) {
737 usecase = node_to_item(node, struct audio_usecase, list);
738 /* Update the in_snd_device only before enabling the audio route */
739 if (switch_device[usecase->id] ) {
740 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800741 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530742 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 }
744 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 }
746}
747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800748/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700749static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700751 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700752 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800753
754 switch (channels) {
755 /*
756 * Do not handle stereo output in Multi-channel cases
757 * Stereo case is handled in normal playback path
758 */
759 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700760 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
761 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766 break;
767 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700768 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775 break;
776 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700777 ALOGE("HDMI does not support multi channel playback");
778 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779 break;
780 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700781 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782}
783
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800784audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
785 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700786{
787 struct audio_usecase *usecase;
788 struct listnode *node;
789
790 list_for_each(node, &adev->usecase_list) {
791 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800792 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700793 ALOGV("%s: usecase id %d", __func__, usecase->id);
794 return usecase->id;
795 }
796 }
797 return USECASE_INVALID;
798}
799
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700800struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700801 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802{
803 struct audio_usecase *usecase;
804 struct listnode *node;
805
806 list_for_each(node, &adev->usecase_list) {
807 usecase = node_to_item(node, struct audio_usecase, list);
808 if (usecase->id == uc_id)
809 return usecase;
810 }
811 return NULL;
812}
813
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700814int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800816 snd_device_t out_snd_device = SND_DEVICE_NONE;
817 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 struct audio_usecase *usecase = NULL;
819 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800820 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800821 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800822 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800823 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700824 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 usecase = get_usecase_from_list(adev, uc_id);
827 if (usecase == NULL) {
828 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
829 return -EINVAL;
830 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800831
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800832 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800833 (usecase->type == VOIP_CALL) ||
834 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700835 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800836 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700837 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 usecase->devices = usecase->stream.out->devices;
839 } else {
840 /*
841 * If the voice call is active, use the sound devices of voice call usecase
842 * so that it would not result any device switch. All the usecases will
843 * be switched to new device when select_devices() is called for voice call
844 * usecase. This is to avoid switching devices for voice call when
845 * check_usecases_codec_backend() is called below.
846 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700847 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700848 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800849 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700850 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
851 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 in_snd_device = vc_usecase->in_snd_device;
853 out_snd_device = vc_usecase->out_snd_device;
854 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800855 } else if (voice_extn_compress_voip_is_active(adev)) {
856 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700857 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530858 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800860 in_snd_device = voip_usecase->in_snd_device;
861 out_snd_device = voip_usecase->out_snd_device;
862 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800863 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800864 hfp_ucid = audio_extn_hfp_get_usecase();
865 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700866 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800867 in_snd_device = hfp_usecase->in_snd_device;
868 out_snd_device = hfp_usecase->out_snd_device;
869 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 }
871 if (usecase->type == PCM_PLAYBACK) {
872 usecase->devices = usecase->stream.out->devices;
873 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700875 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800876 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700877 if (usecase->stream.out == adev->primary_output &&
878 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800879 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 select_devices(adev, adev->active_input->usecase);
881 }
882 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 } else if (usecase->type == PCM_CAPTURE) {
884 usecase->devices = usecase->stream.in->device;
885 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700886 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700887 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530888 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
889 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
890 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
891 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700892 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800893 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700894 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
895 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700896 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700897 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700898 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 }
901
902 if (out_snd_device == usecase->out_snd_device &&
903 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800904 return 0;
905 }
906
sangwoobc677242013-08-08 16:53:43 +0900907 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700908 out_snd_device, platform_get_snd_device_name(out_snd_device),
909 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800911 /*
912 * Limitation: While in call, to do a device switch we need to disable
913 * and enable both RX and TX devices though one of them is same as current
914 * device.
915 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700916 if ((usecase->type == VOICE_CALL) &&
917 (usecase->in_snd_device != SND_DEVICE_NONE) &&
918 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700919 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700920 /* Disable sidetone only if voice call already exists */
921 if (voice_is_call_state_active(adev))
922 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800923 }
924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 /* Disable current sound devices */
926 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700927 disable_audio_route(adev, usecase);
928 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 }
930
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700932 disable_audio_route(adev, usecase);
933 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800934 }
935
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800936 /* Applicable only on the targets that has external modem.
937 * New device information should be sent to modem before enabling
938 * the devices to reduce in-call device switch time.
939 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700940 if ((usecase->type == VOICE_CALL) &&
941 (usecase->in_snd_device != SND_DEVICE_NONE) &&
942 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800943 status = platform_switch_voice_call_enable_device_config(adev->platform,
944 out_snd_device,
945 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700946 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 /* Enable new sound devices */
949 if (out_snd_device != SND_DEVICE_NONE) {
950 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
951 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700952 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953 }
954
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 if (in_snd_device != SND_DEVICE_NONE) {
956 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700957 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959
Avinash Vaish71a8b972014-07-24 15:36:33 +0530960 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700961 status = platform_switch_voice_call_device_post(adev->platform,
962 out_snd_device,
963 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530964 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700965 /* Enable sidetone only if voice call already exists */
966 if (voice_is_call_state_active(adev))
967 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530968 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800969
sangwoo170731f2013-06-08 15:36:36 +0900970 usecase->in_snd_device = in_snd_device;
971 usecase->out_snd_device = out_snd_device;
972
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530973 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700974 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530975 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700976 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530977 usecase->stream.out->flags,
978 usecase->stream.out->format,
979 usecase->stream.out->sample_rate,
980 usecase->stream.out->bit_width,
981 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700982 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530983 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700984
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700985 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900986
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800987 /* Applicable only on the targets that has external modem.
988 * Enable device command should be sent to modem only after
989 * enabling voice call mixer controls
990 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700991 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800992 status = platform_switch_voice_call_usecase_route_post(adev->platform,
993 out_snd_device,
994 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530995 ALOGD("%s: done",__func__);
996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 return status;
998}
999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000static int stop_input_stream(struct stream_in *in)
1001{
1002 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003 struct audio_usecase *uc_info;
1004 struct audio_device *adev = in->dev;
1005
Eric Laurentc8400632013-02-14 19:04:54 -08001006 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007
Eric Laurent994a6932013-07-17 11:51:42 -07001008 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 uc_info = get_usecase_from_list(adev, in->usecase);
1011 if (uc_info == NULL) {
1012 ALOGE("%s: Could not find the usecase (%d) in the list",
1013 __func__, in->usecase);
1014 return -EINVAL;
1015 }
1016
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001017 /* Close in-call recording streams */
1018 voice_check_and_stop_incall_rec_usecase(adev, in);
1019
Eric Laurent150dbfe2013-02-27 14:31:02 -08001020 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022
1023 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001024 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001026 list_remove(&uc_info->list);
1027 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Eric Laurent994a6932013-07-17 11:51:42 -07001029 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030 return ret;
1031}
1032
1033int start_input_stream(struct stream_in *in)
1034{
1035 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001036 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 struct audio_usecase *uc_info;
1038 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301039 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040
Mingming Yine62d7842013-10-25 16:26:03 -07001041 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301042 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1043 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001044
Naresh Tanniru80659832014-06-04 18:17:56 +05301045
1046 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301047 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301048 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301049 goto error_config;
1050 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301051
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001052 /* Check if source matches incall recording usecase criteria */
1053 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1054 if (ret)
1055 goto error_config;
1056 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001057 ALOGD("%s: Updated usecase(%d: %s)",
1058 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001059
Eric Laurentb23d5282013-05-14 15:27:20 -07001060 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 if (in->pcm_device_id < 0) {
1062 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1063 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001064 ret = -EINVAL;
1065 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067
1068 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001070
1071 if (!uc_info) {
1072 ret = -ENOMEM;
1073 goto error_config;
1074 }
1075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076 uc_info->id = in->usecase;
1077 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001078 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 uc_info->devices = in->device;
1080 uc_info->in_snd_device = SND_DEVICE_NONE;
1081 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001083 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301084 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Eric Laurentc8400632013-02-14 19:04:54 -08001087 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001088 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1089
1090 unsigned int flags = PCM_IN;
1091 unsigned int pcm_open_retry_count = 0;
1092
1093 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1094 flags |= PCM_MMAP | PCM_NOIRQ;
1095 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1096 }
1097
1098 while (1) {
1099 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1100 flags, &in->config);
1101 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1102 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1103 if (in->pcm != NULL) {
1104 pcm_close(in->pcm);
1105 in->pcm = NULL;
1106 }
1107 if (pcm_open_retry_count-- == 0) {
1108 ret = -EIO;
1109 goto error_open;
1110 }
1111 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1112 continue;
1113 }
1114 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301116 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301117
Eric Laurent994a6932013-07-17 11:51:42 -07001118 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001119 return ret;
1120
1121error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301123 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001124
1125error_config:
1126 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001128
1129 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130}
1131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001132/* must be called with out->lock locked */
1133static int send_offload_cmd_l(struct stream_out* out, int command)
1134{
1135 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1136
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001137 if (!cmd) {
1138 ALOGE("failed to allocate mem for command 0x%x", command);
1139 return -ENOMEM;
1140 }
1141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001142 ALOGVV("%s %d", __func__, command);
1143
1144 cmd->cmd = command;
1145 list_add_tail(&out->offload_cmd_list, &cmd->node);
1146 pthread_cond_signal(&out->offload_cond);
1147 return 0;
1148}
1149
1150/* must be called iwth out->lock locked */
1151static void stop_compressed_output_l(struct stream_out *out)
1152{
1153 out->offload_state = OFFLOAD_STATE_IDLE;
1154 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001155 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001156 if (out->compr != NULL) {
1157 compress_stop(out->compr);
1158 while (out->offload_thread_blocked) {
1159 pthread_cond_wait(&out->cond, &out->lock);
1160 }
1161 }
1162}
1163
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001164bool is_offload_usecase(audio_usecase_t uc_id)
1165{
1166 unsigned int i;
1167 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1168 if (uc_id == offload_usecases[i])
1169 return true;
1170 }
1171 return false;
1172}
1173
1174static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1175{
1176 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1177 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1178 char value[PROPERTY_VALUE_MAX] = {0};
1179
1180 property_get("audio.offload.multiple.enabled", value, NULL);
1181 if (!(atoi(value) || !strncmp("true", value, 4)))
1182 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1183
1184 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1185 for (i = 0; i < num_usecase; i++) {
1186 if (!(adev->offload_usecases_state & (0x1<<i))) {
1187 adev->offload_usecases_state |= 0x1 << i;
1188 ret = offload_usecases[i];
1189 break;
1190 }
1191 }
1192 ALOGV("%s: offload usecase is %d", __func__, ret);
1193 return ret;
1194}
1195
1196static void free_offload_usecase(struct audio_device *adev,
1197 audio_usecase_t uc_id)
1198{
1199 unsigned int i;
1200 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1201 if (offload_usecases[i] == uc_id) {
1202 adev->offload_usecases_state &= ~(0x1<<i);
1203 break;
1204 }
1205 }
1206 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1207}
1208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001209static void *offload_thread_loop(void *context)
1210{
1211 struct stream_out *out = (struct stream_out *) context;
1212 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001213 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1216 set_sched_policy(0, SP_FOREGROUND);
1217 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1218
1219 ALOGV("%s", __func__);
1220 pthread_mutex_lock(&out->lock);
1221 for (;;) {
1222 struct offload_cmd *cmd = NULL;
1223 stream_callback_event_t event;
1224 bool send_callback = false;
1225
1226 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1227 __func__, list_empty(&out->offload_cmd_list),
1228 out->offload_state);
1229 if (list_empty(&out->offload_cmd_list)) {
1230 ALOGV("%s SLEEPING", __func__);
1231 pthread_cond_wait(&out->offload_cond, &out->lock);
1232 ALOGV("%s RUNNING", __func__);
1233 continue;
1234 }
1235
1236 item = list_head(&out->offload_cmd_list);
1237 cmd = node_to_item(item, struct offload_cmd, node);
1238 list_remove(item);
1239
1240 ALOGVV("%s STATE %d CMD %d out->compr %p",
1241 __func__, out->offload_state, cmd->cmd, out->compr);
1242
1243 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1244 free(cmd);
1245 break;
1246 }
1247
1248 if (out->compr == NULL) {
1249 ALOGE("%s: Compress handle is NULL", __func__);
1250 pthread_cond_signal(&out->cond);
1251 continue;
1252 }
1253 out->offload_thread_blocked = true;
1254 pthread_mutex_unlock(&out->lock);
1255 send_callback = false;
1256 switch(cmd->cmd) {
1257 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001258 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001259 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001260 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001261 send_callback = true;
1262 event = STREAM_CBK_EVENT_WRITE_READY;
1263 break;
1264 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001265 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301266 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001267 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301268 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001269 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301270 if (ret < 0)
1271 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301272 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301273 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001274 compress_drain(out->compr);
1275 else
1276 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301277 if (ret != -ENETRESET) {
1278 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301279 pthread_mutex_lock(&out->lock);
1280 out->send_new_metadata = 1;
1281 out->send_next_track_params = true;
1282 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301283 event = STREAM_CBK_EVENT_DRAIN_READY;
1284 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1285 } else
1286 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001287 break;
1288 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001289 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 send_callback = true;
1293 event = STREAM_CBK_EVENT_DRAIN_READY;
1294 break;
1295 default:
1296 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1297 break;
1298 }
1299 pthread_mutex_lock(&out->lock);
1300 out->offload_thread_blocked = false;
1301 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001302 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001303 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001305 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 free(cmd);
1307 }
1308
1309 pthread_cond_signal(&out->cond);
1310 while (!list_empty(&out->offload_cmd_list)) {
1311 item = list_head(&out->offload_cmd_list);
1312 list_remove(item);
1313 free(node_to_item(item, struct offload_cmd, node));
1314 }
1315 pthread_mutex_unlock(&out->lock);
1316
1317 return NULL;
1318}
1319
1320static int create_offload_callback_thread(struct stream_out *out)
1321{
1322 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1323 list_init(&out->offload_cmd_list);
1324 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1325 offload_thread_loop, out);
1326 return 0;
1327}
1328
1329static int destroy_offload_callback_thread(struct stream_out *out)
1330{
1331 pthread_mutex_lock(&out->lock);
1332 stop_compressed_output_l(out);
1333 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1334
1335 pthread_mutex_unlock(&out->lock);
1336 pthread_join(out->offload_thread, (void **) NULL);
1337 pthread_cond_destroy(&out->offload_cond);
1338
1339 return 0;
1340}
1341
Eric Laurent07eeafd2013-10-06 12:52:49 -07001342static bool allow_hdmi_channel_config(struct audio_device *adev)
1343{
1344 struct listnode *node;
1345 struct audio_usecase *usecase;
1346 bool ret = true;
1347
1348 list_for_each(node, &adev->usecase_list) {
1349 usecase = node_to_item(node, struct audio_usecase, list);
1350 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1351 /*
1352 * If voice call is already existing, do not proceed further to avoid
1353 * disabling/enabling both RX and TX devices, CSD calls, etc.
1354 * Once the voice call done, the HDMI channels can be configured to
1355 * max channels of remaining use cases.
1356 */
1357 if (usecase->id == USECASE_VOICE_CALL) {
1358 ALOGD("%s: voice call is active, no change in HDMI channels",
1359 __func__);
1360 ret = false;
1361 break;
1362 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1363 ALOGD("%s: multi channel playback is active, "
1364 "no change in HDMI channels", __func__);
1365 ret = false;
1366 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001367 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001368 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001369 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1370 ", no change in HDMI channels", __func__,
1371 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001372 ret = false;
1373 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001374 }
1375 }
1376 }
1377 return ret;
1378}
1379
1380static int check_and_set_hdmi_channels(struct audio_device *adev,
1381 unsigned int channels)
1382{
1383 struct listnode *node;
1384 struct audio_usecase *usecase;
1385
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001386 unsigned int supported_channels = platform_edid_get_max_channels(
1387 adev->platform);
1388 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 /* Check if change in HDMI channel config is allowed */
1390 if (!allow_hdmi_channel_config(adev))
1391 return 0;
1392
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001393 if (channels > supported_channels)
1394 channels = supported_channels;
1395
Eric Laurent07eeafd2013-10-06 12:52:49 -07001396 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001397 ALOGD("%s: Requested channels are same as current channels(%d)",
1398 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001399 return 0;
1400 }
1401
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001402 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001404 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001405 adev->cur_hdmi_channels = channels;
1406
1407 /*
1408 * Deroute all the playback streams routed to HDMI so that
1409 * the back end is deactivated. Note that backend will not
1410 * be deactivated if any one stream is connected to it.
1411 */
1412 list_for_each(node, &adev->usecase_list) {
1413 usecase = node_to_item(node, struct audio_usecase, list);
1414 if (usecase->type == PCM_PLAYBACK &&
1415 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001416 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 }
1418 }
1419
1420 /*
1421 * Enable all the streams disabled above. Now the HDMI backend
1422 * will be activated with new channel configuration
1423 */
1424 list_for_each(node, &adev->usecase_list) {
1425 usecase = node_to_item(node, struct audio_usecase, list);
1426 if (usecase->type == PCM_PLAYBACK &&
1427 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001428 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 }
1430 }
1431
1432 return 0;
1433}
1434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435static int stop_output_stream(struct stream_out *out)
1436{
1437 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 struct audio_usecase *uc_info;
1439 struct audio_device *adev = out->dev;
1440
Eric Laurent994a6932013-07-17 11:51:42 -07001441 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 uc_info = get_usecase_from_list(adev, out->usecase);
1444 if (uc_info == NULL) {
1445 ALOGE("%s: Could not find the usecase (%d) in the list",
1446 __func__, out->usecase);
1447 return -EINVAL;
1448 }
1449
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001450 if (is_offload_usecase(out->usecase) &&
1451 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001452 if (adev->visualizer_stop_output != NULL)
1453 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001454
1455 audio_extn_dts_remove_state_notifier_node(out->usecase);
1456
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001457 if (adev->offload_effects_stop_output != NULL)
1458 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1459 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001460
Eric Laurent150dbfe2013-02-27 14:31:02 -08001461 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463
1464 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001465 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001467 list_remove(&uc_info->list);
1468 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001470 if (is_offload_usecase(out->usecase) &&
1471 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1472 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1473 ALOGV("Disable passthrough , reset mixer to pcm");
1474 /* NO_PASSTHROUGH */
1475 out->compr_config.codec->compr_passthr = 0;
1476 audio_extn_dolby_set_hdmi_config(adev, out);
1477 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1478 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001479 /* Must be called after removing the usecase from list */
1480 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1481 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1482
Eric Laurent994a6932013-07-17 11:51:42 -07001483 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 return ret;
1485}
1486
1487int start_output_stream(struct stream_out *out)
1488{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001490 int sink_channels = 0;
1491 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 struct audio_usecase *uc_info;
1493 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301494 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001496 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1497 ret = -EINVAL;
1498 goto error_config;
1499 }
1500
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301501 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1502 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1503 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301504
Naresh Tanniru80659832014-06-04 18:17:56 +05301505 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301506 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301507 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301508 goto error_config;
1509 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301510
Eric Laurentb23d5282013-05-14 15:27:20 -07001511 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 if (out->pcm_device_id < 0) {
1513 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1514 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001515 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001516 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 }
1518
1519 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001520
1521 if (!uc_info) {
1522 ret = -ENOMEM;
1523 goto error_config;
1524 }
1525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 uc_info->id = out->usecase;
1527 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001528 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 uc_info->devices = out->devices;
1530 uc_info->in_snd_device = SND_DEVICE_NONE;
1531 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001532 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001533 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001534 if (is_offload_usecase(out->usecase)) {
1535 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1537 }
1538 }
Mingming Yin9c041392014-05-01 15:37:31 -07001539 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1540 if (!strncmp("true", prop_value, 4)) {
1541 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001542 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1543 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001544 check_and_set_hdmi_channels(adev, sink_channels);
1545 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001546 if (is_offload_usecase(out->usecase)) {
1547 unsigned int ch_count = out->compr_config.codec->ch_in;
1548 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1549 /* backend channel config for passthrough stream is stereo */
1550 ch_count = 2;
1551 check_and_set_hdmi_channels(adev, ch_count);
1552 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001553 check_and_set_hdmi_channels(adev, out->config.channels);
1554 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001555 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001556 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001557 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 select_devices(adev, out->usecase);
1560
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001561 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1562 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001563 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001564 unsigned int flags = PCM_OUT;
1565 unsigned int pcm_open_retry_count = 0;
1566 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1567 flags |= PCM_MMAP | PCM_NOIRQ;
1568 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1569 } else
1570 flags |= PCM_MONOTONIC;
1571
1572 while (1) {
1573 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1574 flags, &out->config);
1575 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1576 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1577 if (out->pcm != NULL) {
1578 pcm_close(out->pcm);
1579 out->pcm = NULL;
1580 }
1581 if (pcm_open_retry_count-- == 0) {
1582 ret = -EIO;
1583 goto error_open;
1584 }
1585 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1586 continue;
1587 }
1588 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001590 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1591 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001592 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001593 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1594 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001596 out->compr = compress_open(adev->snd_card,
1597 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001598 COMPRESS_IN, &out->compr_config);
1599 if (out->compr && !is_compress_ready(out->compr)) {
1600 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1601 compress_close(out->compr);
1602 out->compr = NULL;
1603 ret = -EIO;
1604 goto error_open;
1605 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301606 /* compress_open sends params of the track, so reset the flag here */
1607 out->is_compr_metadata_avail = false;
1608
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 if (out->offload_callback)
1610 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001611
Fred Oh3f43e742015-03-04 18:42:34 -08001612 /* Since small bufs uses blocking writes, a write will be blocked
1613 for the default max poll time (20s) in the event of an SSR.
1614 Reduce the poll time to observe and deal with SSR faster.
1615 */
1616 if (out->use_small_bufs) {
1617 compress_set_max_poll_wait(out->compr, 1000);
1618 }
1619
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001620 audio_extn_dts_create_state_notifier_node(out->usecase);
1621 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1622 popcount(out->channel_mask),
1623 out->playback_started);
1624
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001625#ifdef DS1_DOLBY_DDP_ENABLED
1626 if (audio_extn_is_dolby_format(out->format))
1627 audio_extn_dolby_send_ddp_endp_params(adev);
1628#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001629 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1630 if (adev->visualizer_start_output != NULL)
1631 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1632 if (adev->offload_effects_start_output != NULL)
1633 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001634 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636 }
Eric Laurent994a6932013-07-17 11:51:42 -07001637 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001641error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001642 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643}
1644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645static int check_input_parameters(uint32_t sample_rate,
1646 audio_format_t format,
1647 int channel_count)
1648{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001651 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001652 !voice_extn_compress_voip_is_format_supported(format) &&
1653 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001654
1655 switch (channel_count) {
1656 case 1:
1657 case 2:
1658 case 6:
1659 break;
1660 default:
1661 ret = -EINVAL;
1662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663
1664 switch (sample_rate) {
1665 case 8000:
1666 case 11025:
1667 case 12000:
1668 case 16000:
1669 case 22050:
1670 case 24000:
1671 case 32000:
1672 case 44100:
1673 case 48000:
1674 break;
1675 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001676 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 }
1678
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001679 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680}
1681
1682static size_t get_input_buffer_size(uint32_t sample_rate,
1683 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001684 int channel_count,
1685 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686{
1687 size_t size = 0;
1688
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001689 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1690 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001692 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001693 if (is_low_latency)
1694 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001695 /* ToDo: should use frame_size computed based on the format and
1696 channel_count here. */
1697 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001699 /* make sure the size is multiple of 32 bytes
1700 * At 48 kHz mono 16-bit PCM:
1701 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1702 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1703 */
1704 size += 0x1f;
1705 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001706
1707 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708}
1709
1710static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1711{
1712 struct stream_out *out = (struct stream_out *)stream;
1713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715}
1716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001717static int out_set_sample_rate(struct audio_stream *stream __unused,
1718 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719{
1720 return -ENOSYS;
1721}
1722
1723static size_t out_get_buffer_size(const struct audio_stream *stream)
1724{
1725 struct stream_out *out = (struct stream_out *)stream;
1726
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001727 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001729 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1730 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001732 return out->config.period_size *
1733 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734}
1735
1736static uint32_t out_get_channels(const struct audio_stream *stream)
1737{
1738 struct stream_out *out = (struct stream_out *)stream;
1739
1740 return out->channel_mask;
1741}
1742
1743static audio_format_t out_get_format(const struct audio_stream *stream)
1744{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 struct stream_out *out = (struct stream_out *)stream;
1746
1747 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748}
1749
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001750static int out_set_format(struct audio_stream *stream __unused,
1751 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752{
1753 return -ENOSYS;
1754}
1755
1756static int out_standby(struct audio_stream *stream)
1757{
1758 struct stream_out *out = (struct stream_out *)stream;
1759 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301761 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1762 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001763 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1764 /* Ignore standby in case of voip call because the voip output
1765 * stream is closed in adev_close_output_stream()
1766 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301767 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001768 return 0;
1769 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001773 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001775 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 if (out->pcm) {
1777 pcm_close(out->pcm);
1778 out->pcm = NULL;
1779 }
1780 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001781 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301783 out->send_next_track_params = false;
1784 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001785 out->gapless_mdata.encoder_delay = 0;
1786 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001787 if (out->compr != NULL) {
1788 compress_close(out->compr);
1789 out->compr = NULL;
1790 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001793 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 }
1795 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001796 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 return 0;
1798}
1799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001800static int out_dump(const struct audio_stream *stream __unused,
1801 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802{
1803 return 0;
1804}
1805
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001806static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1807{
1808 int ret = 0;
1809 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001810
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001812 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001813 return -EINVAL;
1814 }
1815
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001816 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1817 if (ret >= 0) {
1818 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1819 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1820 ALOGV("ADTS format is set in offload mode");
1821 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001822 }
1823
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301824 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001825
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1827 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301828 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1831 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301832 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001833 }
1834
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835 ALOGV("%s new encoder delay %u and padding %u", __func__,
1836 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1837
1838 return 0;
1839}
1840
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001841static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1842{
1843 return out == adev->primary_output || out == adev->voice_tx_output;
1844}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1847{
1848 struct stream_out *out = (struct stream_out *)stream;
1849 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001850 struct audio_usecase *usecase;
1851 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 struct str_parms *parms;
1853 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001854 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001855 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856
sangwoobc677242013-08-08 16:53:43 +09001857 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001858 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301860 if (!parms)
1861 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001862 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1863 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001866 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301869 * When HDMI cable is unplugged/usb hs is disconnected the
1870 * music playback is paused and the policy manager sends routing=0
1871 * But the audioflingercontinues to write data until standby time
1872 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 * Avoid this by routing audio to speaker until standby.
1874 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301875 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1876 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001878 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1879 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 }
1881
1882 /*
1883 * select_devices() call below switches all the usecases on the same
1884 * backend to the new device. Refer to check_usecases_codec_backend() in
1885 * the select_devices(). But how do we undo this?
1886 *
1887 * For example, music playback is active on headset (deep-buffer usecase)
1888 * and if we go to ringtones and select a ringtone, low-latency usecase
1889 * will be started on headset+speaker. As we can't enable headset+speaker
1890 * and headset devices at the same time, select_devices() switches the music
1891 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1892 * So when the ringtone playback is completed, how do we undo the same?
1893 *
1894 * We are relying on the out_set_parameters() call on deep-buffer output,
1895 * once the ringtone playback is ended.
1896 * NOTE: We should not check if the current devices are same as new devices.
1897 * Because select_devices() must be called to switch back the music
1898 * playback to headset.
1899 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001900 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 out->devices = val;
1902
1903 if (!out->standby)
1904 select_devices(adev, out->usecase);
1905
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001906 if (output_drives_call(adev, out)) {
1907 if(!voice_is_in_call(adev)) {
1908 if (adev->mode == AUDIO_MODE_IN_CALL) {
1909 adev->current_call_output = out;
1910 ret = voice_start_call(adev);
1911 }
1912 } else {
1913 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001914 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001915 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001916 }
1917 }
1918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001920 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001922
1923 if (out == adev->primary_output) {
1924 pthread_mutex_lock(&adev->lock);
1925 audio_extn_set_parameters(adev, parms);
1926 pthread_mutex_unlock(&adev->lock);
1927 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001928 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001929 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001930 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001931
1932 audio_extn_dts_create_state_notifier_node(out->usecase);
1933 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1934 popcount(out->channel_mask),
1935 out->playback_started);
1936
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001937 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301941error:
Eric Laurent994a6932013-07-17 11:51:42 -07001942 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943 return ret;
1944}
1945
1946static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1947{
1948 struct stream_out *out = (struct stream_out *)stream;
1949 struct str_parms *query = str_parms_create_str(keys);
1950 char *str;
1951 char value[256];
1952 struct str_parms *reply = str_parms_create();
1953 size_t i, j;
1954 int ret;
1955 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001956
1957 if (!query || !reply) {
1958 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1959 return NULL;
1960 }
1961
Eric Laurent994a6932013-07-17 11:51:42 -07001962 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1964 if (ret >= 0) {
1965 value[0] = '\0';
1966 i = 0;
1967 while (out->supported_channel_masks[i] != 0) {
1968 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1969 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1970 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001971 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001973 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 first = false;
1975 break;
1976 }
1977 }
1978 i++;
1979 }
1980 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1981 str = str_parms_to_str(reply);
1982 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001983 voice_extn_out_get_parameters(out, query, reply);
1984 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001985 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001986 free(str);
1987 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001988 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001990
1991 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1992 if (ret >= 0) {
1993 value[0] = '\0';
1994 i = 0;
1995 first = true;
1996 while (out->supported_formats[i] != 0) {
1997 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1998 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1999 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002000 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002001 }
2002 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2003 first = false;
2004 break;
2005 }
2006 }
2007 i++;
2008 }
2009 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2010 str = str_parms_to_str(reply);
2011 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 str_parms_destroy(query);
2013 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002014 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 return str;
2016}
2017
2018static uint32_t out_get_latency(const struct audio_stream_out *stream)
2019{
2020 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002021 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022
Alexy Josephaa54c872014-12-03 02:46:47 -08002023 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002024 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 } else {
2026 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002028 }
2029
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302030 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002031 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032}
2033
2034static int out_set_volume(struct audio_stream_out *stream, float left,
2035 float right)
2036{
Eric Laurenta9024de2013-04-04 09:19:12 -07002037 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 int volume[2];
2039
Eric Laurenta9024de2013-04-04 09:19:12 -07002040 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2041 /* only take left channel into account: the API is for stereo anyway */
2042 out->muted = (left == 0.0f);
2043 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002044 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002045 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2046 /*
2047 * Set mute or umute on HDMI passthrough stream.
2048 * Only take left channel into account.
2049 * Mute is 0 and unmute 1
2050 */
2051 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2052 } else {
2053 char mixer_ctl_name[128];
2054 struct audio_device *adev = out->dev;
2055 struct mixer_ctl *ctl;
2056 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002057 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002059 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2060 "Compress Playback %d Volume", pcm_device_id);
2061 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2062 if (!ctl) {
2063 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2064 __func__, mixer_ctl_name);
2065 return -EINVAL;
2066 }
2067 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2068 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2069 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2070 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002072 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 return -ENOSYS;
2075}
2076
2077static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2078 size_t bytes)
2079{
2080 struct stream_out *out = (struct stream_out *)stream;
2081 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302082 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002083 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302086
Naresh Tanniru80659832014-06-04 18:17:56 +05302087 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002088 // increase written size during SSR to avoid mismatch
2089 // with the written frames count in AF
2090 if (!is_offload_usecase(out->usecase))
2091 out->written += bytes / (out->config.channels * sizeof(short));
2092
Naresh Tanniru80659832014-06-04 18:17:56 +05302093 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302094 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302095 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302096 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002097 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302098 //during SSR for compress usecase we should return error to flinger
2099 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2100 pthread_mutex_unlock(&out->lock);
2101 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302102 }
2103 }
2104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002106 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002107 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002108 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2109 ret = voice_extn_compress_voip_start_output_stream(out);
2110 else
2111 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002112 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002115 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 goto exit;
2117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302120 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2121 setChannelStatus(out, buffer, bytes);
2122 adev->mChannelStatusSet = true;
2123 }
2124
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002125 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002126 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002127 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002128 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002129 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2130 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302131 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2132 ALOGD("copl(%p):send next track params in gapless", out);
2133 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2134 out->send_next_track_params = false;
2135 out->is_compr_metadata_avail = false;
2136 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002137 }
2138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302140 if (ret < 0)
2141 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002142 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002143 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302144 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302146 } else if (-ENETRESET == ret) {
2147 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2148 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2149 pthread_mutex_unlock(&out->lock);
2150 out_standby(&out->stream.common);
2151 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302153 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002155 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 out->playback_started = 1;
2157 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002158
2159 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2160 popcount(out->channel_mask),
2161 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 }
2163 pthread_mutex_unlock(&out->lock);
2164 return ret;
2165 } else {
2166 if (out->pcm) {
2167 if (out->muted)
2168 memset((void *)buffer, 0, bytes);
2169 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002170 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2171 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2172 else
2173 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302174 if (ret < 0)
2175 ret = -errno;
2176 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002177 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 }
2180
2181exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302182 /* ToDo: There may be a corner case when SSR happens back to back during
2183 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302184 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302185 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302186 }
2187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 pthread_mutex_unlock(&out->lock);
2189
2190 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002191 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002192 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302193 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302194 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302195 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302196 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302197 out->standby = true;
2198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002200 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302201 out_get_sample_rate(&out->stream.common));
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 }
2204 return bytes;
2205}
2206
2207static int out_get_render_position(const struct audio_stream_out *stream,
2208 uint32_t *dsp_frames)
2209{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302211 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002212
2213 if (dsp_frames == NULL)
2214 return -EINVAL;
2215
2216 *dsp_frames = 0;
2217 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002218 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 pthread_mutex_lock(&out->lock);
2220 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302221 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302223 if (ret < 0)
2224 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 ALOGVV("%s rendered frames %d sample_rate %d",
2226 __func__, *dsp_frames, out->sample_rate);
2227 }
2228 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 if (-ENETRESET == ret) {
2230 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2231 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2232 return -EINVAL;
2233 } else if(ret < 0) {
2234 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2235 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302236 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2237 /*
2238 * Handle corner case where compress session is closed during SSR
2239 * and timestamp is queried
2240 */
2241 ALOGE(" ERROR: sound card not active, return error");
2242 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302243 } else {
2244 return 0;
2245 }
Zhou Song32a556e2015-05-05 10:46:56 +08002246 } else if (audio_is_linear_pcm(out->format)) {
2247 *dsp_frames = out->written;
2248 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 } else
2250 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251}
2252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002253static int out_add_audio_effect(const struct audio_stream *stream __unused,
2254 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255{
2256 return 0;
2257}
2258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002259static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2260 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261{
2262 return 0;
2263}
2264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002265static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2266 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267{
2268 return -EINVAL;
2269}
2270
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002271static int out_get_presentation_position(const struct audio_stream_out *stream,
2272 uint64_t *frames, struct timespec *timestamp)
2273{
2274 struct stream_out *out = (struct stream_out *)stream;
2275 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002276 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002277
2278 pthread_mutex_lock(&out->lock);
2279
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002280 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002281 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302282 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002283 &out->sample_rate);
2284 ALOGVV("%s rendered frames %ld sample_rate %d",
2285 __func__, dsp_frames, out->sample_rate);
2286 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302287 if (ret < 0)
2288 ret = -errno;
2289 if (-ENETRESET == ret) {
2290 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2291 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2292 ret = -EINVAL;
2293 } else
2294 ret = 0;
2295
Eric Laurent949a0892013-09-20 09:20:13 -07002296 /* this is the best we can do */
2297 clock_gettime(CLOCK_MONOTONIC, timestamp);
2298 }
2299 } else {
2300 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002301 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002302 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2303 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002304 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002305 // This adjustment accounts for buffering after app processor.
2306 // It is based on estimated DSP latency per use case, rather than exact.
2307 signed_frames -=
2308 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2309
Eric Laurent949a0892013-09-20 09:20:13 -07002310 // It would be unusual for this value to be negative, but check just in case ...
2311 if (signed_frames >= 0) {
2312 *frames = signed_frames;
2313 ret = 0;
2314 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002315 }
2316 }
2317 }
2318
2319 pthread_mutex_unlock(&out->lock);
2320
2321 return ret;
2322}
2323
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324static int out_set_callback(struct audio_stream_out *stream,
2325 stream_callback_t callback, void *cookie)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328
2329 ALOGV("%s", __func__);
2330 pthread_mutex_lock(&out->lock);
2331 out->offload_callback = callback;
2332 out->offload_cookie = cookie;
2333 pthread_mutex_unlock(&out->lock);
2334 return 0;
2335}
2336
2337static int out_pause(struct audio_stream_out* stream)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340 int status = -ENOSYS;
2341 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002342 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002343 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 pthread_mutex_lock(&out->lock);
2345 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302346 struct audio_device *adev = out->dev;
2347 int snd_scard_state = get_snd_card_state(adev);
2348
2349 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2350 status = compress_pause(out->compr);
2351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002353
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302354 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002355 audio_extn_dts_notify_playback_state(out->usecase, 0,
2356 out->sample_rate, popcount(out->channel_mask),
2357 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 }
2359 pthread_mutex_unlock(&out->lock);
2360 }
2361 return status;
2362}
2363
2364static int out_resume(struct audio_stream_out* stream)
2365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367 int status = -ENOSYS;
2368 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002369 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002370 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 status = 0;
2372 pthread_mutex_lock(&out->lock);
2373 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302374 struct audio_device *adev = out->dev;
2375 int snd_scard_state = get_snd_card_state(adev);
2376
2377 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2378 status = compress_resume(out->compr);
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002381
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302382 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2384 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 }
2386 pthread_mutex_unlock(&out->lock);
2387 }
2388 return status;
2389}
2390
2391static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 int status = -ENOSYS;
2395 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002396 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 pthread_mutex_lock(&out->lock);
2398 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2399 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2400 else
2401 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2402 pthread_mutex_unlock(&out->lock);
2403 }
2404 return status;
2405}
2406
2407static int out_flush(struct audio_stream_out* stream)
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002412 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 pthread_mutex_lock(&out->lock);
2414 stop_compressed_output_l(out);
2415 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002416 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 return 0;
2418 }
2419 return -ENOSYS;
2420}
2421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422/** audio_stream_in implementation **/
2423static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
2427 return in->config.rate;
2428}
2429
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002430static int in_set_sample_rate(struct audio_stream *stream __unused,
2431 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 return -ENOSYS;
2434}
2435
2436static size_t in_get_buffer_size(const struct audio_stream *stream)
2437{
2438 struct stream_in *in = (struct stream_in *)stream;
2439
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2441 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002442 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2443 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002444
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002445 return in->config.period_size *
2446 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447}
2448
2449static uint32_t in_get_channels(const struct audio_stream *stream)
2450{
2451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->channel_mask;
2454}
2455
2456static audio_format_t in_get_format(const struct audio_stream *stream)
2457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002458 struct stream_in *in = (struct stream_in *)stream;
2459
2460 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461}
2462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002463static int in_set_format(struct audio_stream *stream __unused,
2464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465{
2466 return -ENOSYS;
2467}
2468
2469static int in_standby(struct audio_stream *stream)
2470{
2471 struct stream_in *in = (struct stream_in *)stream;
2472 struct audio_device *adev = in->dev;
2473 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302474 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2475 stream, in->usecase, use_case_table[in->usecase]);
2476
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2478 /* Ignore standby in case of voip call because the voip input
2479 * stream is closed in adev_close_input_stream()
2480 */
2481 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2482 return status;
2483 }
2484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002486 if (!in->standby && in->is_st_session) {
2487 ALOGD("%s: sound trigger pcm stop lab", __func__);
2488 audio_extn_sound_trigger_stop_lab(in);
2489 in->standby = 1;
2490 }
2491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002493 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002495 if (in->pcm) {
2496 pcm_close(in->pcm);
2497 in->pcm = NULL;
2498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002500 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 }
2502 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002503 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 return status;
2505}
2506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002507static int in_dump(const struct audio_stream *stream __unused,
2508 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509{
2510 return 0;
2511}
2512
2513static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2514{
2515 struct stream_in *in = (struct stream_in *)stream;
2516 struct audio_device *adev = in->dev;
2517 struct str_parms *parms;
2518 char *str;
2519 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002520 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302522 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 parms = str_parms_create_str(kvpairs);
2524
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302525 if (!parms)
2526 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002528 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002529
2530 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2531 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 val = atoi(value);
2533 /* no audio source uses val == 0 */
2534 if ((in->source != val) && (val != 0)) {
2535 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002536 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2537 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2538 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2539 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002540 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002541 err = voice_extn_compress_voip_open_input_stream(in);
2542 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002543 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002544 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002545 }
2546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 }
2548 }
2549
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002550 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2551 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002553 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 in->device = val;
2555 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002556 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002557 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 }
2559 }
2560
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002561done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002563 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564
2565 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302566error:
Eric Laurent994a6932013-07-17 11:51:42 -07002567 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 return ret;
2569}
2570
2571static char* in_get_parameters(const struct audio_stream *stream,
2572 const char *keys)
2573{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 struct stream_in *in = (struct stream_in *)stream;
2575 struct str_parms *query = str_parms_create_str(keys);
2576 char *str;
2577 char value[256];
2578 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002579
2580 if (!query || !reply) {
2581 ALOGE("in_get_parameters: failed to create query or reply");
2582 return NULL;
2583 }
2584
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002585 ALOGV("%s: enter: keys - %s", __func__, keys);
2586
2587 voice_extn_in_get_parameters(in, query, reply);
2588
2589 str = str_parms_to_str(reply);
2590 str_parms_destroy(query);
2591 str_parms_destroy(reply);
2592
2593 ALOGV("%s: exit: returns - %s", __func__, str);
2594 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595}
2596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002597static int in_set_gain(struct audio_stream_in *stream __unused,
2598 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599{
2600 return 0;
2601}
2602
2603static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2604 size_t bytes)
2605{
2606 struct stream_in *in = (struct stream_in *)stream;
2607 struct audio_device *adev = in->dev;
2608 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302609 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302612
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002613 if (in->is_st_session) {
2614 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2615 /* Read from sound trigger HAL */
2616 audio_extn_sound_trigger_read(in, buffer, bytes);
2617 pthread_mutex_unlock(&in->lock);
2618 return bytes;
2619 }
2620
2621 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2622 ALOGD(" %s: sound card is not active/SSR state", __func__);
2623 ret= -EIO;;
2624 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302625 }
2626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002628 pthread_mutex_lock(&adev->lock);
2629 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2630 ret = voice_extn_compress_voip_start_input_stream(in);
2631 else
2632 ret = start_input_stream(in);
2633 pthread_mutex_unlock(&adev->lock);
2634 if (ret != 0) {
2635 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 }
2637 in->standby = 0;
2638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639
2640 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002641 if (audio_extn_ssr_get_enabled() &&
2642 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002643 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002644 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2645 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002646 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2647 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002648 else
2649 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302650 if (ret < 0)
2651 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 }
2653
2654 /*
2655 * Instead of writing zeroes here, we could trust the hardware
2656 * to always provide zeroes when muted.
2657 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302658 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2659 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 memset(buffer, 0, bytes);
2661
2662exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302663 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302664 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002665 if (-ENETRESET == ret)
2666 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 pthread_mutex_unlock(&in->lock);
2669
2670 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302671 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302672 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302673 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302674 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302675 in->standby = true;
2676 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302677 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002679 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002680 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302681 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 }
2683 return bytes;
2684}
2685
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002686static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687{
2688 return 0;
2689}
2690
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002691static int add_remove_audio_effect(const struct audio_stream *stream,
2692 effect_handle_t effect,
2693 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002695 struct stream_in *in = (struct stream_in *)stream;
2696 int status = 0;
2697 effect_descriptor_t desc;
2698
2699 status = (*effect)->get_descriptor(effect, &desc);
2700 if (status != 0)
2701 return status;
2702
2703 pthread_mutex_lock(&in->lock);
2704 pthread_mutex_lock(&in->dev->lock);
2705 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2706 in->enable_aec != enable &&
2707 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2708 in->enable_aec = enable;
2709 if (!in->standby)
2710 select_devices(in->dev, in->usecase);
2711 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002712 if (in->enable_ns != enable &&
2713 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2714 in->enable_ns = enable;
2715 if (!in->standby)
2716 select_devices(in->dev, in->usecase);
2717 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002718 pthread_mutex_unlock(&in->dev->lock);
2719 pthread_mutex_unlock(&in->lock);
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 return 0;
2722}
2723
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724static int in_add_audio_effect(const struct audio_stream *stream,
2725 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726{
Eric Laurent994a6932013-07-17 11:51:42 -07002727 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002728 return add_remove_audio_effect(stream, effect, true);
2729}
2730
2731static int in_remove_audio_effect(const struct audio_stream *stream,
2732 effect_handle_t effect)
2733{
Eric Laurent994a6932013-07-17 11:51:42 -07002734 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002735 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736}
2737
2738static int adev_open_output_stream(struct audio_hw_device *dev,
2739 audio_io_handle_t handle,
2740 audio_devices_t devices,
2741 audio_output_flags_t flags,
2742 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002743 struct audio_stream_out **stream_out,
2744 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
2746 struct audio_device *adev = (struct audio_device *)dev;
2747 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002748 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002749 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302752
2753 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2754 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2755 ALOGE(" sound card is not active rejecting compress output open request");
2756 return -EINVAL;
2757 }
2758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2760
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302761 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2762 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2763 devices, flags, &out->stream);
2764
2765
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002766 if (!out) {
2767 return -ENOMEM;
2768 }
2769
Haynes Mathew George204045b2015-02-25 20:32:03 -08002770 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2771 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 if (devices == AUDIO_DEVICE_NONE)
2774 devices = AUDIO_DEVICE_OUT_SPEAKER;
2775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 out->flags = flags;
2777 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002778 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002779 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 out->sample_rate = config->sample_rate;
2781 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2782 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002783 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002784 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002785 out->non_blocking = 0;
2786 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002788 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2789 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002790 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2791 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2792
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002793 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002794 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2795 ret = read_hdmi_channel_masks(out);
2796
2797 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2798 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002800 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002801 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002802
2803 if (config->sample_rate == 0)
2804 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2805 if (config->channel_mask == 0)
2806 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2807
2808 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2811 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002813 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002815 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2816 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002817 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002818 ret = voice_extn_compress_voip_open_output_stream(out);
2819 if (ret != 0) {
2820 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2821 __func__, ret);
2822 goto error_open;
2823 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2825 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2826 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2827 ALOGE("%s: Unsupported Offload information", __func__);
2828 ret = -EINVAL;
2829 goto error_open;
2830 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002831
2832 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2833 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2834 ALOGV("read and update_pass through formats");
2835 ret = audio_extn_dolby_update_passt_formats(adev, out);
2836 if(ret != 0) {
2837 goto error_open;
2838 }
2839 if(config->offload_info.format == 0)
2840 config->offload_info.format = out->supported_formats[0];
2841 }
2842
Mingming Yin90310102013-11-13 16:57:00 -08002843 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002844 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 ALOGE("%s: Unsupported audio format", __func__);
2846 ret = -EINVAL;
2847 goto error_open;
2848 }
2849
2850 out->compr_config.codec = (struct snd_codec *)
2851 calloc(1, sizeof(struct snd_codec));
2852
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002853 if (!out->compr_config.codec) {
2854 ret = -ENOMEM;
2855 goto error_open;
2856 }
2857
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002858 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 if (config->offload_info.channel_mask)
2860 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002861 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002863 config->offload_info.channel_mask = config->channel_mask;
2864 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002865 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 out->sample_rate = config->offload_info.sample_rate;
2867
2868 out->stream.set_callback = out_set_callback;
2869 out->stream.pause = out_pause;
2870 out->stream.resume = out_resume;
2871 out->stream.drain = out_drain;
2872 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002873 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002875 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002876 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002877 audio_extn_dolby_get_snd_codec_id(adev, out,
2878 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002879 else
2880 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002882 if (audio_is_offload_pcm(config->offload_info.format)) {
2883 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884 platform_get_pcm_offload_buffer_size(&config->offload_info);
2885 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2886 out->compr_config.fragment_size =
2887 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002888 } else {
2889 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002890 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002891 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2893 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002894 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 out->compr_config.codec->bit_rate =
2896 config->offload_info.bit_rate;
2897 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002898 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002900 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002901 /*TODO: Do we need to change it for passthrough */
2902 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903
Mingming Yin3ee55c62014-08-04 14:23:35 -07002904 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2905 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2907 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002909 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2910
Mingming Yin3ee55c62014-08-04 14:23:35 -07002911 if (out->bit_width == 24) {
2912 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2913 }
2914
Amit Shekhar6f461b12014-08-01 14:52:58 -07002915 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002916 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2919 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002920
Alexy Josephaa54c872014-12-03 02:46:47 -08002921 if (config->offload_info.use_small_bufs) {
2922 //this flag is set from framework only if its for PCM formats
2923 //no need to check for PCM format again
2924 out->non_blocking = 0;
2925 out->use_small_bufs = true;
2926 ALOGI("Keep write blocking for small buff: non_blockling %d",
2927 out->non_blocking);
2928 }
2929
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002930 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302931 out->send_next_track_params = false;
2932 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002933 out->offload_state = OFFLOAD_STATE_IDLE;
2934 out->playback_started = 0;
2935
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002936 audio_extn_dts_create_state_notifier_node(out->usecase);
2937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 create_offload_callback_thread(out);
2939 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2940 __func__, config->offload_info.version,
2941 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002942 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002943 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002944 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2945 ret = voice_check_and_set_incall_music_usecase(adev, out);
2946 if (ret != 0) {
2947 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2948 __func__, ret);
2949 goto error_open;
2950 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002951 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2952 if (config->sample_rate == 0)
2953 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2954 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2955 config->sample_rate != 8000) {
2956 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2957 ret = -EINVAL;
2958 goto error_open;
2959 }
2960 out->sample_rate = config->sample_rate;
2961 out->config.rate = config->sample_rate;
2962 if (config->format == AUDIO_FORMAT_DEFAULT)
2963 config->format = AUDIO_FORMAT_PCM_16_BIT;
2964 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2965 config->format = AUDIO_FORMAT_PCM_16_BIT;
2966 ret = -EINVAL;
2967 goto error_open;
2968 }
2969 out->format = config->format;
2970 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2971 out->config = pcm_config_afe_proxy_playback;
2972 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002973 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002974 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2976 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002978 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2979 format = AUDIO_FORMAT_PCM_16_BIT;
2980 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2981 out->config = pcm_config_deep_buffer;
2982 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002983 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002984 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002985 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002986 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002987 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002988 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 }
2990
Amit Shekhar1d896042014-10-03 13:16:09 -07002991 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2992 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002993 /* TODO remove this hardcoding and check why width is zero*/
2994 if (out->bit_width == 0)
2995 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002996 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2997 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002998 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302999 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003000 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3001 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3002 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003003 if(adev->primary_output == NULL)
3004 adev->primary_output = out;
3005 else {
3006 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003007 ret = -EEXIST;
3008 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003009 }
3010 }
3011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 /* Check if this usecase is already existing */
3013 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003014 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3015 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003018 ret = -EEXIST;
3019 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 }
3021 pthread_mutex_unlock(&adev->lock);
3022
3023 out->stream.common.get_sample_rate = out_get_sample_rate;
3024 out->stream.common.set_sample_rate = out_set_sample_rate;
3025 out->stream.common.get_buffer_size = out_get_buffer_size;
3026 out->stream.common.get_channels = out_get_channels;
3027 out->stream.common.get_format = out_get_format;
3028 out->stream.common.set_format = out_set_format;
3029 out->stream.common.standby = out_standby;
3030 out->stream.common.dump = out_dump;
3031 out->stream.common.set_parameters = out_set_parameters;
3032 out->stream.common.get_parameters = out_get_parameters;
3033 out->stream.common.add_audio_effect = out_add_audio_effect;
3034 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3035 out->stream.get_latency = out_get_latency;
3036 out->stream.set_volume = out_set_volume;
3037 out->stream.write = out_write;
3038 out->stream.get_render_position = out_get_render_position;
3039 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003040 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003043 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003044 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045
3046 config->format = out->stream.common.get_format(&out->stream.common);
3047 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3048 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3049
3050 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303051 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3052 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003053
3054 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3055 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3056 popcount(out->channel_mask), out->playback_started);
3057
Eric Laurent994a6932013-07-17 11:51:42 -07003058 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003060
3061error_open:
3062 free(out);
3063 *stream_out = NULL;
3064 ALOGD("%s: exit: ret %d", __func__, ret);
3065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066}
3067
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003068static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 struct audio_stream_out *stream)
3070{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 struct stream_out *out = (struct stream_out *)stream;
3072 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303075 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3076
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003077 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303078 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303080 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 if(ret != 0)
3082 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3083 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003084 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003085 out_standby(&stream->common);
3086
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003087 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003088 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003090 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 if (out->compr_config.codec != NULL)
3092 free(out->compr_config.codec);
3093 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003094
3095 if (adev->voice_tx_output == out)
3096 adev->voice_tx_output = NULL;
3097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 pthread_cond_destroy(&out->cond);
3099 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003101 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102}
3103
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003104static void close_compress_sessions(struct audio_device *adev)
3105{
Mingming Yin7b762e72015-03-04 13:47:32 -08003106 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303107 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003108 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003109 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303110
3111 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303113 if (is_offload_usecase(usecase->id)) {
3114 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003115 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3116 out = usecase->stream.out;
3117 pthread_mutex_unlock(&adev->lock);
3118 out_standby(&out->stream.common);
3119 pthread_mutex_lock(&adev->lock);
3120 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303121 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003122 }
3123 pthread_mutex_unlock(&adev->lock);
3124}
3125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3127{
3128 struct audio_device *adev = (struct audio_device *)dev;
3129 struct str_parms *parms;
3130 char *str;
3131 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003132 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003133 int ret;
3134 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003136 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303139 if (!parms)
3140 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003141 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3142 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 struct listnode *node;
3146 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303147 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303148 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003149 //close compress sessions on OFFLINE status
3150 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 } else if (strstr(snd_card_status, "ONLINE")) {
3152 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303153 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303154 if (!platform_is_acdb_initialized(adev->platform)) {
3155 ret = platform_acdb_init(adev->platform);
3156 if(ret)
3157 ALOGE("acdb initialization is failed");
3158
3159 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303160 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 }
3162
3163 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003164 status = voice_set_parameters(adev, parms);
3165 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003166 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003168 status = platform_set_parameters(adev->platform, parms);
3169 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003170 goto done;
3171
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003172 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3173 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003174 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3176 adev->bluetooth_nrec = true;
3177 else
3178 adev->bluetooth_nrec = false;
3179 }
3180
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003181 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3182 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3184 adev->screen_off = false;
3185 else
3186 adev->screen_off = true;
3187 }
3188
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003189 ret = str_parms_get_int(parms, "rotation", &val);
3190 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003191 bool reverse_speakers = false;
3192 switch(val) {
3193 // FIXME: note that the code below assumes that the speakers are in the correct placement
3194 // relative to the user when the device is rotated 90deg from its default rotation. This
3195 // assumption is device-specific, not platform-specific like this code.
3196 case 270:
3197 reverse_speakers = true;
3198 break;
3199 case 0:
3200 case 90:
3201 case 180:
3202 break;
3203 default:
3204 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003205 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003206 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003207 if (status == 0) {
3208 if (adev->speaker_lr_swap != reverse_speakers) {
3209 adev->speaker_lr_swap = reverse_speakers;
3210 // only update the selected device if there is active pcm playback
3211 struct audio_usecase *usecase;
3212 struct listnode *node;
3213 list_for_each(node, &adev->usecase_list) {
3214 usecase = node_to_item(node, struct audio_usecase, list);
3215 if (usecase->type == PCM_PLAYBACK) {
3216 select_devices(adev, usecase->id);
3217 break;
3218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003219 }
3220 }
3221 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003222 }
3223
Mingming Yin514a8bc2014-07-29 15:22:21 -07003224 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3225 if (ret >= 0) {
3226 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3227 adev->bt_wb_speech_enabled = true;
3228 else
3229 adev->bt_wb_speech_enabled = false;
3230 }
3231
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3233 if (ret >= 0) {
3234 val = atoi(value);
3235 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3236 ALOGV("cache new edid");
3237 platform_cache_edid(adev->platform);
3238 }
3239 }
3240
3241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3242 if (ret >= 0) {
3243 val = atoi(value);
3244 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3245 ALOGV("invalidate cached edid");
3246 platform_invalidate_edid(adev->platform);
3247 }
3248 }
3249
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003250 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003251
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003252done:
3253 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003254 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303255error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003256 ALOGV("%s: exit with code(%d)", __func__, status);
3257 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258}
3259
3260static char* adev_get_parameters(const struct audio_hw_device *dev,
3261 const char *keys)
3262{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003263 struct audio_device *adev = (struct audio_device *)dev;
3264 struct str_parms *reply = str_parms_create();
3265 struct str_parms *query = str_parms_create_str(keys);
3266 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303267 char value[256] = {0};
3268 int ret = 0;
3269
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003270 if (!query || !reply) {
3271 ALOGE("adev_get_parameters: failed to create query or reply");
3272 return NULL;
3273 }
3274
Naresh Tannirud7205b62014-06-20 02:54:48 +05303275 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3276 sizeof(value));
3277 if (ret >=0) {
3278 int val = 1;
3279 pthread_mutex_lock(&adev->snd_card_status.lock);
3280 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3281 val = 0;
3282 pthread_mutex_unlock(&adev->snd_card_status.lock);
3283 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3284 goto exit;
3285 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003286
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003287 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003288 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003289 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003290 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303291 pthread_mutex_unlock(&adev->lock);
3292
Naresh Tannirud7205b62014-06-20 02:54:48 +05303293exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003294 str = str_parms_to_str(reply);
3295 str_parms_destroy(query);
3296 str_parms_destroy(reply);
3297
3298 ALOGV("%s: exit: returns - %s", __func__, str);
3299 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300}
3301
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003302static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303{
3304 return 0;
3305}
3306
3307static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3308{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003309 int ret;
3310 struct audio_device *adev = (struct audio_device *)dev;
3311 pthread_mutex_lock(&adev->lock);
3312 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003313 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003314 pthread_mutex_unlock(&adev->lock);
3315 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316}
3317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003318static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3319 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320{
3321 return -ENOSYS;
3322}
3323
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003324static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3325 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326{
3327 return -ENOSYS;
3328}
3329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003330static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3331 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332{
3333 return -ENOSYS;
3334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3337 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338{
3339 return -ENOSYS;
3340}
3341
3342static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3343{
3344 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 pthread_mutex_lock(&adev->lock);
3347 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003348 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003350 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3351 voice_is_in_call(adev)) {
3352 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303353 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003354 adev->current_call_output = NULL;
3355 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 }
3357 pthread_mutex_unlock(&adev->lock);
3358 return 0;
3359}
3360
3361static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3362{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003363 int ret;
3364
3365 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003366 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003367 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3368 pthread_mutex_unlock(&adev->lock);
3369
3370 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371}
3372
3373static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3374{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003375 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 return 0;
3377}
3378
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003379static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 const struct audio_config *config)
3381{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003382 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003384 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3385 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386}
3387
3388static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003389 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 audio_devices_t devices,
3391 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003392 struct audio_stream_in **stream_in,
3393 audio_input_flags_t flags __unused,
3394 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003395 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396{
3397 struct audio_device *adev = (struct audio_device *)dev;
3398 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003399 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003400 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003401 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 *stream_in = NULL;
3404 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3405 return -EINVAL;
3406
3407 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003408
3409 if (!in) {
3410 ALOGE("failed to allocate input stream");
3411 return -ENOMEM;
3412 }
3413
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303414 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003415 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3416 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003418 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 in->stream.common.get_sample_rate = in_get_sample_rate;
3421 in->stream.common.set_sample_rate = in_set_sample_rate;
3422 in->stream.common.get_buffer_size = in_get_buffer_size;
3423 in->stream.common.get_channels = in_get_channels;
3424 in->stream.common.get_format = in_get_format;
3425 in->stream.common.set_format = in_set_format;
3426 in->stream.common.standby = in_standby;
3427 in->stream.common.dump = in_dump;
3428 in->stream.common.set_parameters = in_set_parameters;
3429 in->stream.common.get_parameters = in_get_parameters;
3430 in->stream.common.add_audio_effect = in_add_audio_effect;
3431 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3432 in->stream.set_gain = in_set_gain;
3433 in->stream.read = in_read;
3434 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3435
3436 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003437 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->standby = 1;
3440 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003441 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442
3443 /* Update config params with the requested sample rate and channels */
3444 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003445 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3446 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3447 is_low_latency = true;
3448#if LOW_LATENCY_CAPTURE_USE_CASE
3449 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3450#endif
3451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003454 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003456 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303457 if (adev->mode != AUDIO_MODE_IN_CALL) {
3458 ret = -EINVAL;
3459 goto err_open;
3460 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003461 if (config->sample_rate == 0)
3462 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3463 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3464 config->sample_rate != 8000) {
3465 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3466 ret = -EINVAL;
3467 goto err_open;
3468 }
3469 if (config->format == AUDIO_FORMAT_DEFAULT)
3470 config->format = AUDIO_FORMAT_PCM_16_BIT;
3471 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3472 config->format = AUDIO_FORMAT_PCM_16_BIT;
3473 ret = -EINVAL;
3474 goto err_open;
3475 }
3476
3477 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3478 in->config = pcm_config_afe_proxy_record;
3479 in->config.channels = channel_count;
3480 in->config.rate = config->sample_rate;
3481 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003482 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003484 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3485 ret = -EINVAL;
3486 goto err_open;
3487 }
3488 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003489 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003490 }
Mingming Yine62d7842013-10-25 16:26:03 -07003491 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003492 audio_extn_compr_cap_format_supported(config->format) &&
3493 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003494 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003495 } else {
3496 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003497 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003498 buffer_size = get_input_buffer_size(config->sample_rate,
3499 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003500 channel_count,
3501 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003502 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003503 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3504 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3505 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3506 (in->config.rate == 8000 || in->config.rate == 16000) &&
3507 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3508 voice_extn_compress_voip_open_input_stream(in);
3509 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003512 /* This stream could be for sound trigger lab,
3513 get sound trigger pcm if present */
3514 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303515 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003518 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003519 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
3521err_open:
3522 free(in);
3523 *stream_in = NULL;
3524 return ret;
3525}
3526
3527static void adev_close_input_stream(struct audio_hw_device *dev,
3528 struct audio_stream_in *stream)
3529{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003531 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003532 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303533
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303534 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003535
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303536 /* Disable echo reference while closing input stream */
3537 platform_set_echo_reference(adev->platform, false);
3538
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003539 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303540 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003541 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303542 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003543 if (ret != 0)
3544 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3545 __func__, ret);
3546 } else
3547 in_standby(&stream->common);
3548
Mingming Yin7b762e72015-03-04 13:47:32 -08003549 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003550 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003551 audio_extn_ssr_deinit();
3552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Mingming Yine62d7842013-10-25 16:26:03 -07003554 if(audio_extn_compr_cap_enabled() &&
3555 audio_extn_compr_cap_format_supported(in->config.format))
3556 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003557
3558 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 return;
3560}
3561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003562static int adev_dump(const audio_hw_device_t *device __unused,
3563 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564{
3565 return 0;
3566}
3567
3568static int adev_close(hw_device_t *device)
3569{
3570 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003571
3572 if (!adev)
3573 return 0;
3574
3575 pthread_mutex_lock(&adev_init_lock);
3576
3577 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003578 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003579 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003580 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003581 audio_route_free(adev->audio_route);
3582 free(adev->snd_dev_ref_cnt);
3583 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003584 free(device);
3585 adev = NULL;
3586 }
3587 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 return 0;
3589}
3590
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003591/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3592 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3593 * just that it _might_ work.
3594 */
3595static int period_size_is_plausible_for_low_latency(int period_size)
3596{
3597 switch (period_size) {
3598 case 160:
3599 case 240:
3600 case 320:
3601 case 480:
3602 return 1;
3603 default:
3604 return 0;
3605 }
3606}
3607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608static int adev_open(const hw_module_t *module, const char *name,
3609 hw_device_t **device)
3610{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003611 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003613 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3615
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003616 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003617 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003618 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003619 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003620 ALOGD("%s: returning existing instance of adev", __func__);
3621 ALOGD("%s: exit", __func__);
3622 pthread_mutex_unlock(&adev_init_lock);
3623 return 0;
3624 }
3625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 adev = calloc(1, sizeof(struct audio_device));
3627
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003628 if (!adev) {
3629 pthread_mutex_unlock(&adev_init_lock);
3630 return -ENOMEM;
3631 }
3632
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003633 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3636 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3637 adev->device.common.module = (struct hw_module_t *)module;
3638 adev->device.common.close = adev_close;
3639
3640 adev->device.init_check = adev_init_check;
3641 adev->device.set_voice_volume = adev_set_voice_volume;
3642 adev->device.set_master_volume = adev_set_master_volume;
3643 adev->device.get_master_volume = adev_get_master_volume;
3644 adev->device.set_master_mute = adev_set_master_mute;
3645 adev->device.get_master_mute = adev_get_master_mute;
3646 adev->device.set_mode = adev_set_mode;
3647 adev->device.set_mic_mute = adev_set_mic_mute;
3648 adev->device.get_mic_mute = adev_get_mic_mute;
3649 adev->device.set_parameters = adev_set_parameters;
3650 adev->device.get_parameters = adev_get_parameters;
3651 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3652 adev->device.open_output_stream = adev_open_output_stream;
3653 adev->device.close_output_stream = adev_close_output_stream;
3654 adev->device.open_input_stream = adev_open_input_stream;
3655 adev->device.close_input_stream = adev_close_input_stream;
3656 adev->device.dump = adev_dump;
3657
3658 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003660 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003661 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003664 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003665 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003666 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003667 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003668 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003669 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003670 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303671 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303672
3673 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3674 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003676 adev->platform = platform_init(adev);
3677 if (!adev->platform) {
3678 free(adev->snd_dev_ref_cnt);
3679 free(adev);
3680 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3681 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003682 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003683 return -EINVAL;
3684 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003685
Naresh Tanniru4c630392014-05-12 01:05:52 +05303686 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3687
Eric Laurentc4aef752013-09-12 17:45:53 -07003688 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3689 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3690 if (adev->visualizer_lib == NULL) {
3691 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3692 } else {
3693 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3694 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003695 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003696 "visualizer_hal_start_output");
3697 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003698 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003699 "visualizer_hal_stop_output");
3700 }
3701 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003702 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003703 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003704
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003705 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3706 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3707 if (adev->offload_effects_lib == NULL) {
3708 ALOGE("%s: DLOPEN failed for %s", __func__,
3709 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3710 } else {
3711 ALOGV("%s: DLOPEN successful for %s", __func__,
3712 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3713 adev->offload_effects_start_output =
3714 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3715 "offload_effects_bundle_hal_start_output");
3716 adev->offload_effects_stop_output =
3717 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3718 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003719 adev->offload_effects_set_hpx_state =
3720 (int (*)(bool))dlsym(adev->offload_effects_lib,
3721 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003722 }
3723 }
3724
Mingming Yin514a8bc2014-07-29 15:22:21 -07003725 adev->bt_wb_speech_enabled = false;
3726
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003727 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 *device = &adev->device.common;
3729
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003730 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3731 &adev->streams_output_cfg_list);
3732
Kiran Kandi910e1862013-10-29 13:29:42 -07003733 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003734
3735 char value[PROPERTY_VALUE_MAX];
3736 int trial;
3737 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3738 trial = atoi(value);
3739 if (period_size_is_plausible_for_low_latency(trial)) {
3740 pcm_config_low_latency.period_size = trial;
3741 pcm_config_low_latency.start_threshold = trial / 4;
3742 pcm_config_low_latency.avail_min = trial / 4;
3743 configured_low_latency_capture_period_size = trial;
3744 }
3745 }
3746 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3747 trial = atoi(value);
3748 if (period_size_is_plausible_for_low_latency(trial)) {
3749 configured_low_latency_capture_period_size = trial;
3750 }
3751 }
3752
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003753 pthread_mutex_unlock(&adev_init_lock);
3754
Eric Laurent994a6932013-07-17 11:51:42 -07003755 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 return 0;
3757}
3758
3759static struct hw_module_methods_t hal_module_methods = {
3760 .open = adev_open,
3761};
3762
3763struct audio_module HAL_MODULE_INFO_SYM = {
3764 .common = {
3765 .tag = HARDWARE_MODULE_TAG,
3766 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3767 .hal_api_version = HARDWARE_HAL_API_VERSION,
3768 .id = AUDIO_HARDWARE_MODULE_ID,
3769 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003770 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 .methods = &hal_module_methods,
3772 },
3773};