blob: 821b339ed262e996fd8c3905e9fa36ea2bdae7df [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 Gutta5d596582015-08-20 12:30:33 +0530666 /* Update the out_snd_device only before enabling the audio route */
667 if (switch_device[usecase->id] ) {
668 usecase->out_snd_device = snd_device;
669 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530670 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 }
672 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 }
674}
675
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700676static void check_and_route_capture_usecases(struct audio_device *adev,
677 struct audio_usecase *uc_info,
678 snd_device_t snd_device)
679{
680 struct listnode *node;
681 struct audio_usecase *usecase;
682 bool switch_device[AUDIO_USECASE_MAX];
683 int i, num_uc_to_switch = 0;
684
685 /*
686 * This function is to make sure that all the active capture usecases
687 * are always routed to the same input sound device.
688 * For example, if audio-record and voice-call usecases are currently
689 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
690 * is received for voice call then we have to make sure that audio-record
691 * usecase is also switched to earpiece i.e. voice-dmic-ef,
692 * because of the limitation that two devices cannot be enabled
693 * at the same time if they share the same backend.
694 */
695 for (i = 0; i < AUDIO_USECASE_MAX; i++)
696 switch_device[i] = false;
697
698 list_for_each(node, &adev->usecase_list) {
699 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800700 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700702 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700703 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530704 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
705 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700706 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
708 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700709 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700710 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711 switch_device[usecase->id] = true;
712 num_uc_to_switch++;
713 }
714 }
715
716 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700717 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530719 /* Make sure the previous devices to be disabled first and then enable the
720 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700724 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800725 }
726 }
727
728 list_for_each(node, &adev->usecase_list) {
729 usecase = node_to_item(node, struct audio_usecase, list);
730 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700731 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 }
733 }
734
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735 /* Re-route all the usecases on the shared backend other than the
736 specified usecase to new snd devices */
737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 /* Update the in_snd_device only before enabling the audio route */
740 if (switch_device[usecase->id] ) {
741 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800742 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530743 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744 }
745 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746 }
747}
748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700750static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700752 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700753 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754
755 switch (channels) {
756 /*
757 * Do not handle stereo output in Multi-channel cases
758 * Stereo case is handled in normal playback path
759 */
760 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767 break;
768 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700769 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 break;
777 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700778 ALOGE("HDMI does not support multi channel playback");
779 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780 break;
781 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700782 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783}
784
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800785audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
786 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700787{
788 struct audio_usecase *usecase;
789 struct listnode *node;
790
791 list_for_each(node, &adev->usecase_list) {
792 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800793 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700794 ALOGV("%s: usecase id %d", __func__, usecase->id);
795 return usecase->id;
796 }
797 }
798 return USECASE_INVALID;
799}
800
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700801struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700802 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
809 if (usecase->id == uc_id)
810 return usecase;
811 }
812 return NULL;
813}
814
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800817 snd_device_t out_snd_device = SND_DEVICE_NONE;
818 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 struct audio_usecase *usecase = NULL;
820 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800821 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800822 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800823 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800824 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 usecase = get_usecase_from_list(adev, uc_id);
828 if (usecase == NULL) {
829 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
830 return -EINVAL;
831 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800833 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800834 (usecase->type == VOIP_CALL) ||
835 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700836 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800837 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700838 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 usecase->devices = usecase->stream.out->devices;
840 } else {
841 /*
842 * If the voice call is active, use the sound devices of voice call usecase
843 * so that it would not result any device switch. All the usecases will
844 * be switched to new device when select_devices() is called for voice call
845 * usecase. This is to avoid switching devices for voice call when
846 * check_usecases_codec_backend() is called below.
847 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700848 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700849 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800850 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700851 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
852 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 in_snd_device = vc_usecase->in_snd_device;
854 out_snd_device = vc_usecase->out_snd_device;
855 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800856 } else if (voice_extn_compress_voip_is_active(adev)) {
857 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700858 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530859 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800861 in_snd_device = voip_usecase->in_snd_device;
862 out_snd_device = voip_usecase->out_snd_device;
863 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800864 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800865 hfp_ucid = audio_extn_hfp_get_usecase();
866 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800868 in_snd_device = hfp_usecase->in_snd_device;
869 out_snd_device = hfp_usecase->out_snd_device;
870 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 }
872 if (usecase->type == PCM_PLAYBACK) {
873 usecase->devices = usecase->stream.out->devices;
874 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700875 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700876 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800877 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700878 if (usecase->stream.out == adev->primary_output &&
879 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800880 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 select_devices(adev, adev->active_input->usecase);
882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 } else if (usecase->type == PCM_CAPTURE) {
885 usecase->devices = usecase->stream.in->device;
886 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700887 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530889 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
890 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
891 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
892 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700893 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800894 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700895 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
896 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700898 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 }
901 }
902
903 if (out_snd_device == usecase->out_snd_device &&
904 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 return 0;
906 }
907
sangwoobc677242013-08-08 16:53:43 +0900908 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700909 out_snd_device, platform_get_snd_device_name(out_snd_device),
910 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 /*
913 * Limitation: While in call, to do a device switch we need to disable
914 * and enable both RX and TX devices though one of them is same as current
915 * device.
916 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700917 if ((usecase->type == VOICE_CALL) &&
918 (usecase->in_snd_device != SND_DEVICE_NONE) &&
919 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700920 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700921 /* Disable sidetone only if voice call already exists */
922 if (voice_is_call_state_active(adev))
923 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800924 }
925
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 /* Disable current sound devices */
927 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700928 disable_audio_route(adev, usecase);
929 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800930 }
931
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700933 disable_audio_route(adev, usecase);
934 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 }
936
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800937 /* Applicable only on the targets that has external modem.
938 * New device information should be sent to modem before enabling
939 * the devices to reduce in-call device switch time.
940 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700941 if ((usecase->type == VOICE_CALL) &&
942 (usecase->in_snd_device != SND_DEVICE_NONE) &&
943 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800944 status = platform_switch_voice_call_enable_device_config(adev->platform,
945 out_snd_device,
946 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700947 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800948
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700949 /* Enable new sound devices */
950 if (out_snd_device != SND_DEVICE_NONE) {
951 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
952 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700953 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954 }
955
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700956 if (in_snd_device != SND_DEVICE_NONE) {
957 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700958 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960
Avinash Vaish71a8b972014-07-24 15:36:33 +0530961 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700962 status = platform_switch_voice_call_device_post(adev->platform,
963 out_snd_device,
964 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530965 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700966 /* Enable sidetone only if voice call already exists */
967 if (voice_is_call_state_active(adev))
968 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530969 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800970
sangwoo170731f2013-06-08 15:36:36 +0900971 usecase->in_snd_device = in_snd_device;
972 usecase->out_snd_device = out_snd_device;
973
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530974 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700975 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530976 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700977 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530978 usecase->stream.out->flags,
979 usecase->stream.out->format,
980 usecase->stream.out->sample_rate,
981 usecase->stream.out->bit_width,
982 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700983 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530984 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700985
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700986 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900987
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800988 /* Applicable only on the targets that has external modem.
989 * Enable device command should be sent to modem only after
990 * enabling voice call mixer controls
991 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700992 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800993 status = platform_switch_voice_call_usecase_route_post(adev->platform,
994 out_snd_device,
995 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530996 ALOGD("%s: done",__func__);
997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 return status;
999}
1000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001static int stop_input_stream(struct stream_in *in)
1002{
1003 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004 struct audio_usecase *uc_info;
1005 struct audio_device *adev = in->dev;
1006
Eric Laurentc8400632013-02-14 19:04:54 -08001007 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008
Eric Laurent994a6932013-07-17 11:51:42 -07001009 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001011 uc_info = get_usecase_from_list(adev, in->usecase);
1012 if (uc_info == NULL) {
1013 ALOGE("%s: Could not find the usecase (%d) in the list",
1014 __func__, in->usecase);
1015 return -EINVAL;
1016 }
1017
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001018 /* Close in-call recording streams */
1019 voice_check_and_stop_incall_rec_usecase(adev, in);
1020
Eric Laurent150dbfe2013-02-27 14:31:02 -08001021 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001022 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023
1024 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001025 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001027 list_remove(&uc_info->list);
1028 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029
Eric Laurent994a6932013-07-17 11:51:42 -07001030 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 return ret;
1032}
1033
1034int start_input_stream(struct stream_in *in)
1035{
1036 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001037 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 struct audio_usecase *uc_info;
1039 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301040 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Mingming Yine62d7842013-10-25 16:26:03 -07001042 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301043 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1044 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001045
Naresh Tanniru80659832014-06-04 18:17:56 +05301046
1047 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301048 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301049 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301050 goto error_config;
1051 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301052
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001053 /* Check if source matches incall recording usecase criteria */
1054 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1055 if (ret)
1056 goto error_config;
1057 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001058 ALOGD("%s: Updated usecase(%d: %s)",
1059 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001060
Eric Laurentb23d5282013-05-14 15:27:20 -07001061 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 if (in->pcm_device_id < 0) {
1063 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1064 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001065 ret = -EINVAL;
1066 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068
1069 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001071
1072 if (!uc_info) {
1073 ret = -ENOMEM;
1074 goto error_config;
1075 }
1076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 uc_info->id = in->usecase;
1078 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001079 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 uc_info->devices = in->device;
1081 uc_info->in_snd_device = SND_DEVICE_NONE;
1082 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001084 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301085 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087
Eric Laurentc8400632013-02-14 19:04:54 -08001088 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001089 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1090
1091 unsigned int flags = PCM_IN;
1092 unsigned int pcm_open_retry_count = 0;
1093
1094 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1095 flags |= PCM_MMAP | PCM_NOIRQ;
1096 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1097 }
1098
1099 while (1) {
1100 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1101 flags, &in->config);
1102 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1103 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1104 if (in->pcm != NULL) {
1105 pcm_close(in->pcm);
1106 in->pcm = NULL;
1107 }
1108 if (pcm_open_retry_count-- == 0) {
1109 ret = -EIO;
1110 goto error_open;
1111 }
1112 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1113 continue;
1114 }
1115 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301117 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301118
Eric Laurent994a6932013-07-17 11:51:42 -07001119 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001120 return ret;
1121
1122error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301124 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001125
1126error_config:
1127 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001129
1130 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131}
1132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001133/* must be called with out->lock locked */
1134static int send_offload_cmd_l(struct stream_out* out, int command)
1135{
1136 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1137
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001138 if (!cmd) {
1139 ALOGE("failed to allocate mem for command 0x%x", command);
1140 return -ENOMEM;
1141 }
1142
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001143 ALOGVV("%s %d", __func__, command);
1144
1145 cmd->cmd = command;
1146 list_add_tail(&out->offload_cmd_list, &cmd->node);
1147 pthread_cond_signal(&out->offload_cond);
1148 return 0;
1149}
1150
1151/* must be called iwth out->lock locked */
1152static void stop_compressed_output_l(struct stream_out *out)
1153{
1154 out->offload_state = OFFLOAD_STATE_IDLE;
1155 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001156 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001157 if (out->compr != NULL) {
1158 compress_stop(out->compr);
1159 while (out->offload_thread_blocked) {
1160 pthread_cond_wait(&out->cond, &out->lock);
1161 }
1162 }
1163}
1164
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001165bool is_offload_usecase(audio_usecase_t uc_id)
1166{
1167 unsigned int i;
1168 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1169 if (uc_id == offload_usecases[i])
1170 return true;
1171 }
1172 return false;
1173}
1174
1175static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1176{
1177 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1178 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1179 char value[PROPERTY_VALUE_MAX] = {0};
1180
1181 property_get("audio.offload.multiple.enabled", value, NULL);
1182 if (!(atoi(value) || !strncmp("true", value, 4)))
1183 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1184
1185 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1186 for (i = 0; i < num_usecase; i++) {
1187 if (!(adev->offload_usecases_state & (0x1<<i))) {
1188 adev->offload_usecases_state |= 0x1 << i;
1189 ret = offload_usecases[i];
1190 break;
1191 }
1192 }
1193 ALOGV("%s: offload usecase is %d", __func__, ret);
1194 return ret;
1195}
1196
1197static void free_offload_usecase(struct audio_device *adev,
1198 audio_usecase_t uc_id)
1199{
1200 unsigned int i;
1201 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1202 if (offload_usecases[i] == uc_id) {
1203 adev->offload_usecases_state &= ~(0x1<<i);
1204 break;
1205 }
1206 }
1207 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1208}
1209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210static void *offload_thread_loop(void *context)
1211{
1212 struct stream_out *out = (struct stream_out *) context;
1213 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001214 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001216 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1217 set_sched_policy(0, SP_FOREGROUND);
1218 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1219
1220 ALOGV("%s", __func__);
1221 pthread_mutex_lock(&out->lock);
1222 for (;;) {
1223 struct offload_cmd *cmd = NULL;
1224 stream_callback_event_t event;
1225 bool send_callback = false;
1226
1227 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1228 __func__, list_empty(&out->offload_cmd_list),
1229 out->offload_state);
1230 if (list_empty(&out->offload_cmd_list)) {
1231 ALOGV("%s SLEEPING", __func__);
1232 pthread_cond_wait(&out->offload_cond, &out->lock);
1233 ALOGV("%s RUNNING", __func__);
1234 continue;
1235 }
1236
1237 item = list_head(&out->offload_cmd_list);
1238 cmd = node_to_item(item, struct offload_cmd, node);
1239 list_remove(item);
1240
1241 ALOGVV("%s STATE %d CMD %d out->compr %p",
1242 __func__, out->offload_state, cmd->cmd, out->compr);
1243
1244 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1245 free(cmd);
1246 break;
1247 }
1248
1249 if (out->compr == NULL) {
1250 ALOGE("%s: Compress handle is NULL", __func__);
1251 pthread_cond_signal(&out->cond);
1252 continue;
1253 }
1254 out->offload_thread_blocked = true;
1255 pthread_mutex_unlock(&out->lock);
1256 send_callback = false;
1257 switch(cmd->cmd) {
1258 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001259 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001261 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001262 send_callback = true;
1263 event = STREAM_CBK_EVENT_WRITE_READY;
1264 break;
1265 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001266 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301267 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001268 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301269 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001270 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301271 if (ret < 0)
1272 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301273 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301274 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001275 compress_drain(out->compr);
1276 else
1277 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301278 if (ret != -ENETRESET) {
1279 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301280 pthread_mutex_lock(&out->lock);
1281 out->send_new_metadata = 1;
1282 out->send_next_track_params = true;
1283 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301284 event = STREAM_CBK_EVENT_DRAIN_READY;
1285 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1286 } else
1287 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001288 break;
1289 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001290 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001291 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001292 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001293 send_callback = true;
1294 event = STREAM_CBK_EVENT_DRAIN_READY;
1295 break;
1296 default:
1297 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1298 break;
1299 }
1300 pthread_mutex_lock(&out->lock);
1301 out->offload_thread_blocked = false;
1302 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001303 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001304 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001306 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 free(cmd);
1308 }
1309
1310 pthread_cond_signal(&out->cond);
1311 while (!list_empty(&out->offload_cmd_list)) {
1312 item = list_head(&out->offload_cmd_list);
1313 list_remove(item);
1314 free(node_to_item(item, struct offload_cmd, node));
1315 }
1316 pthread_mutex_unlock(&out->lock);
1317
1318 return NULL;
1319}
1320
1321static int create_offload_callback_thread(struct stream_out *out)
1322{
1323 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1324 list_init(&out->offload_cmd_list);
1325 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1326 offload_thread_loop, out);
1327 return 0;
1328}
1329
1330static int destroy_offload_callback_thread(struct stream_out *out)
1331{
1332 pthread_mutex_lock(&out->lock);
1333 stop_compressed_output_l(out);
1334 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1335
1336 pthread_mutex_unlock(&out->lock);
1337 pthread_join(out->offload_thread, (void **) NULL);
1338 pthread_cond_destroy(&out->offload_cond);
1339
1340 return 0;
1341}
1342
Eric Laurent07eeafd2013-10-06 12:52:49 -07001343static bool allow_hdmi_channel_config(struct audio_device *adev)
1344{
1345 struct listnode *node;
1346 struct audio_usecase *usecase;
1347 bool ret = true;
1348
1349 list_for_each(node, &adev->usecase_list) {
1350 usecase = node_to_item(node, struct audio_usecase, list);
1351 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1352 /*
1353 * If voice call is already existing, do not proceed further to avoid
1354 * disabling/enabling both RX and TX devices, CSD calls, etc.
1355 * Once the voice call done, the HDMI channels can be configured to
1356 * max channels of remaining use cases.
1357 */
1358 if (usecase->id == USECASE_VOICE_CALL) {
1359 ALOGD("%s: voice call is active, no change in HDMI channels",
1360 __func__);
1361 ret = false;
1362 break;
1363 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1364 ALOGD("%s: multi channel playback is active, "
1365 "no change in HDMI channels", __func__);
1366 ret = false;
1367 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001368 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001369 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001370 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1371 ", no change in HDMI channels", __func__,
1372 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001373 ret = false;
1374 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001375 }
1376 }
1377 }
1378 return ret;
1379}
1380
1381static int check_and_set_hdmi_channels(struct audio_device *adev,
1382 unsigned int channels)
1383{
1384 struct listnode *node;
1385 struct audio_usecase *usecase;
1386
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001387 unsigned int supported_channels = platform_edid_get_max_channels(
1388 adev->platform);
1389 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001390 /* Check if change in HDMI channel config is allowed */
1391 if (!allow_hdmi_channel_config(adev))
1392 return 0;
1393
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001394 if (channels > supported_channels)
1395 channels = supported_channels;
1396
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001398 ALOGD("%s: Requested channels are same as current channels(%d)",
1399 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001400 return 0;
1401 }
1402
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001403 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001404 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001405 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001406 adev->cur_hdmi_channels = channels;
1407
1408 /*
1409 * Deroute all the playback streams routed to HDMI so that
1410 * the back end is deactivated. Note that backend will not
1411 * be deactivated if any one stream is connected to it.
1412 */
1413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
1415 if (usecase->type == PCM_PLAYBACK &&
1416 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001417 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001418 }
1419 }
1420
1421 /*
1422 * Enable all the streams disabled above. Now the HDMI backend
1423 * will be activated with new channel configuration
1424 */
1425 list_for_each(node, &adev->usecase_list) {
1426 usecase = node_to_item(node, struct audio_usecase, list);
1427 if (usecase->type == PCM_PLAYBACK &&
1428 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001429 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 }
1431 }
1432
1433 return 0;
1434}
1435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436static int stop_output_stream(struct stream_out *out)
1437{
1438 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 struct audio_usecase *uc_info;
1440 struct audio_device *adev = out->dev;
1441
Eric Laurent994a6932013-07-17 11:51:42 -07001442 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 uc_info = get_usecase_from_list(adev, out->usecase);
1445 if (uc_info == NULL) {
1446 ALOGE("%s: Could not find the usecase (%d) in the list",
1447 __func__, out->usecase);
1448 return -EINVAL;
1449 }
1450
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001451 if (is_offload_usecase(out->usecase) &&
1452 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001453 if (adev->visualizer_stop_output != NULL)
1454 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001455
1456 audio_extn_dts_remove_state_notifier_node(out->usecase);
1457
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001458 if (adev->offload_effects_stop_output != NULL)
1459 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1460 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001461
Eric Laurent150dbfe2013-02-27 14:31:02 -08001462 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001463 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464
1465 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001466 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001468 list_remove(&uc_info->list);
1469 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001471 if (is_offload_usecase(out->usecase) &&
1472 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1473 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1474 ALOGV("Disable passthrough , reset mixer to pcm");
1475 /* NO_PASSTHROUGH */
1476 out->compr_config.codec->compr_passthr = 0;
1477 audio_extn_dolby_set_hdmi_config(adev, out);
1478 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1479 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001480 /* Must be called after removing the usecase from list */
1481 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1482 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1483
Eric Laurent994a6932013-07-17 11:51:42 -07001484 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 return ret;
1486}
1487
1488int start_output_stream(struct stream_out *out)
1489{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001491 int sink_channels = 0;
1492 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 struct audio_usecase *uc_info;
1494 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301495 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001497 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1498 ret = -EINVAL;
1499 goto error_config;
1500 }
1501
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301502 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1503 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1504 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301505
Naresh Tanniru80659832014-06-04 18:17:56 +05301506 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301507 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301508 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301509 goto error_config;
1510 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301511
Eric Laurentb23d5282013-05-14 15:27:20 -07001512 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 if (out->pcm_device_id < 0) {
1514 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1515 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001516 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001517 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 }
1519
1520 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001521
1522 if (!uc_info) {
1523 ret = -ENOMEM;
1524 goto error_config;
1525 }
1526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527 uc_info->id = out->usecase;
1528 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001529 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 uc_info->devices = out->devices;
1531 uc_info->in_snd_device = SND_DEVICE_NONE;
1532 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001533 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001534 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001535 if (is_offload_usecase(out->usecase)) {
1536 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001537 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1538 }
1539 }
Mingming Yin9c041392014-05-01 15:37:31 -07001540 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1541 if (!strncmp("true", prop_value, 4)) {
1542 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001543 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1544 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001545 check_and_set_hdmi_channels(adev, sink_channels);
1546 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001547 if (is_offload_usecase(out->usecase)) {
1548 unsigned int ch_count = out->compr_config.codec->ch_in;
1549 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1550 /* backend channel config for passthrough stream is stereo */
1551 ch_count = 2;
1552 check_and_set_hdmi_channels(adev, ch_count);
1553 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001554 check_and_set_hdmi_channels(adev, out->config.channels);
1555 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001556 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001557 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001558 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 select_devices(adev, out->usecase);
1561
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001562 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1563 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001564 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001565 unsigned int flags = PCM_OUT;
1566 unsigned int pcm_open_retry_count = 0;
1567 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1568 flags |= PCM_MMAP | PCM_NOIRQ;
1569 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1570 } else
1571 flags |= PCM_MONOTONIC;
1572
1573 while (1) {
1574 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1575 flags, &out->config);
1576 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1577 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1578 if (out->pcm != NULL) {
1579 pcm_close(out->pcm);
1580 out->pcm = NULL;
1581 }
1582 if (pcm_open_retry_count-- == 0) {
1583 ret = -EIO;
1584 goto error_open;
1585 }
1586 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1587 continue;
1588 }
1589 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001591 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1592 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001593 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001594 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1595 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001597 out->compr = compress_open(adev->snd_card,
1598 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001599 COMPRESS_IN, &out->compr_config);
1600 if (out->compr && !is_compress_ready(out->compr)) {
1601 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1602 compress_close(out->compr);
1603 out->compr = NULL;
1604 ret = -EIO;
1605 goto error_open;
1606 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301607 /* compress_open sends params of the track, so reset the flag here */
1608 out->is_compr_metadata_avail = false;
1609
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001610 if (out->offload_callback)
1611 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001612
Fred Oh3f43e742015-03-04 18:42:34 -08001613 /* Since small bufs uses blocking writes, a write will be blocked
1614 for the default max poll time (20s) in the event of an SSR.
1615 Reduce the poll time to observe and deal with SSR faster.
1616 */
1617 if (out->use_small_bufs) {
1618 compress_set_max_poll_wait(out->compr, 1000);
1619 }
1620
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001621 audio_extn_dts_create_state_notifier_node(out->usecase);
1622 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1623 popcount(out->channel_mask),
1624 out->playback_started);
1625
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001626#ifdef DS1_DOLBY_DDP_ENABLED
1627 if (audio_extn_is_dolby_format(out->format))
1628 audio_extn_dolby_send_ddp_endp_params(adev);
1629#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001630 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1631 if (adev->visualizer_start_output != NULL)
1632 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1633 if (adev->offload_effects_start_output != NULL)
1634 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001635 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 }
Eric Laurent994a6932013-07-17 11:51:42 -07001638 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001640error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001642error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001643 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644}
1645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646static int check_input_parameters(uint32_t sample_rate,
1647 audio_format_t format,
1648 int channel_count)
1649{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001650 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001652 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001653 !voice_extn_compress_voip_is_format_supported(format) &&
1654 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001655
1656 switch (channel_count) {
1657 case 1:
1658 case 2:
1659 case 6:
1660 break;
1661 default:
1662 ret = -EINVAL;
1663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664
1665 switch (sample_rate) {
1666 case 8000:
1667 case 11025:
1668 case 12000:
1669 case 16000:
1670 case 22050:
1671 case 24000:
1672 case 32000:
1673 case 44100:
1674 case 48000:
1675 break;
1676 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001677 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 }
1679
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001680 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681}
1682
1683static size_t get_input_buffer_size(uint32_t sample_rate,
1684 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001685 int channel_count,
1686 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687{
1688 size_t size = 0;
1689
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001690 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1691 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001693 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001694 if (is_low_latency)
1695 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001696 /* ToDo: should use frame_size computed based on the format and
1697 channel_count here. */
1698 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001700 /* make sure the size is multiple of 32 bytes
1701 * At 48 kHz mono 16-bit PCM:
1702 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1703 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1704 */
1705 size += 0x1f;
1706 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001707
1708 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709}
1710
1711static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1712{
1713 struct stream_out *out = (struct stream_out *)stream;
1714
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716}
1717
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001718static int out_set_sample_rate(struct audio_stream *stream __unused,
1719 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720{
1721 return -ENOSYS;
1722}
1723
1724static size_t out_get_buffer_size(const struct audio_stream *stream)
1725{
1726 struct stream_out *out = (struct stream_out *)stream;
1727
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001728 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001729 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001730 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1731 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001733 return out->config.period_size *
1734 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735}
1736
1737static uint32_t out_get_channels(const struct audio_stream *stream)
1738{
1739 struct stream_out *out = (struct stream_out *)stream;
1740
1741 return out->channel_mask;
1742}
1743
1744static audio_format_t out_get_format(const struct audio_stream *stream)
1745{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 struct stream_out *out = (struct stream_out *)stream;
1747
1748 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749}
1750
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001751static int out_set_format(struct audio_stream *stream __unused,
1752 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753{
1754 return -ENOSYS;
1755}
1756
1757static int out_standby(struct audio_stream *stream)
1758{
1759 struct stream_out *out = (struct stream_out *)stream;
1760 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001761
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301762 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1763 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001764 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1765 /* Ignore standby in case of voip call because the voip output
1766 * stream is closed in adev_close_output_stream()
1767 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301768 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001769 return 0;
1770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001774 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001776 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777 if (out->pcm) {
1778 pcm_close(out->pcm);
1779 out->pcm = NULL;
1780 }
1781 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001782 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301784 out->send_next_track_params = false;
1785 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001786 out->gapless_mdata.encoder_delay = 0;
1787 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 if (out->compr != NULL) {
1789 compress_close(out->compr);
1790 out->compr = NULL;
1791 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001794 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 }
1796 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001797 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 return 0;
1799}
1800
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001801static int out_dump(const struct audio_stream *stream __unused,
1802 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803{
1804 return 0;
1805}
1806
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1808{
1809 int ret = 0;
1810 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001811
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001813 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 return -EINVAL;
1815 }
1816
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1818 if (ret >= 0) {
1819 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1820 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1821 ALOGV("ADTS format is set in offload mode");
1822 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001823 }
1824
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301825 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001826
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1828 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301829 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001831 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1832 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301833 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 }
1835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836 ALOGV("%s new encoder delay %u and padding %u", __func__,
1837 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1838
1839 return 0;
1840}
1841
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001842static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1843{
1844 return out == adev->primary_output || out == adev->voice_tx_output;
1845}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1848{
1849 struct stream_out *out = (struct stream_out *)stream;
1850 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001851 struct audio_usecase *usecase;
1852 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 struct str_parms *parms;
1854 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001855 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001856 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857
sangwoobc677242013-08-08 16:53:43 +09001858 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001859 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301861 if (!parms)
1862 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001863 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1864 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001867 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301870 * When HDMI cable is unplugged/usb hs is disconnected the
1871 * music playback is paused and the policy manager sends routing=0
1872 * But the audioflingercontinues to write data until standby time
1873 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 * Avoid this by routing audio to speaker until standby.
1875 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301876 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1877 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001879 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1880 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 }
1882
1883 /*
1884 * select_devices() call below switches all the usecases on the same
1885 * backend to the new device. Refer to check_usecases_codec_backend() in
1886 * the select_devices(). But how do we undo this?
1887 *
1888 * For example, music playback is active on headset (deep-buffer usecase)
1889 * and if we go to ringtones and select a ringtone, low-latency usecase
1890 * will be started on headset+speaker. As we can't enable headset+speaker
1891 * and headset devices at the same time, select_devices() switches the music
1892 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1893 * So when the ringtone playback is completed, how do we undo the same?
1894 *
1895 * We are relying on the out_set_parameters() call on deep-buffer output,
1896 * once the ringtone playback is ended.
1897 * NOTE: We should not check if the current devices are same as new devices.
1898 * Because select_devices() must be called to switch back the music
1899 * playback to headset.
1900 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001901 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902 out->devices = val;
1903
1904 if (!out->standby)
1905 select_devices(adev, out->usecase);
1906
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001907 if (output_drives_call(adev, out)) {
1908 if(!voice_is_in_call(adev)) {
1909 if (adev->mode == AUDIO_MODE_IN_CALL) {
1910 adev->current_call_output = out;
1911 ret = voice_start_call(adev);
1912 }
1913 } else {
1914 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001915 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001916 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001917 }
1918 }
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001921 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001923
1924 if (out == adev->primary_output) {
1925 pthread_mutex_lock(&adev->lock);
1926 audio_extn_set_parameters(adev, parms);
1927 pthread_mutex_unlock(&adev->lock);
1928 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001929 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001930 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001932
1933 audio_extn_dts_create_state_notifier_node(out->usecase);
1934 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1935 popcount(out->channel_mask),
1936 out->playback_started);
1937
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001938 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301942error:
Eric Laurent994a6932013-07-17 11:51:42 -07001943 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 return ret;
1945}
1946
1947static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1948{
1949 struct stream_out *out = (struct stream_out *)stream;
1950 struct str_parms *query = str_parms_create_str(keys);
1951 char *str;
1952 char value[256];
1953 struct str_parms *reply = str_parms_create();
1954 size_t i, j;
1955 int ret;
1956 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001957
1958 if (!query || !reply) {
1959 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1960 return NULL;
1961 }
1962
Eric Laurent994a6932013-07-17 11:51:42 -07001963 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1965 if (ret >= 0) {
1966 value[0] = '\0';
1967 i = 0;
1968 while (out->supported_channel_masks[i] != 0) {
1969 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1970 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1971 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001972 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001974 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 first = false;
1976 break;
1977 }
1978 }
1979 i++;
1980 }
1981 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1982 str = str_parms_to_str(reply);
1983 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001984 voice_extn_out_get_parameters(out, query, reply);
1985 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001986 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001987 free(str);
1988 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001989 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001991
1992 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1993 if (ret >= 0) {
1994 value[0] = '\0';
1995 i = 0;
1996 first = true;
1997 while (out->supported_formats[i] != 0) {
1998 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1999 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2000 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002001 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002002 }
2003 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2004 first = false;
2005 break;
2006 }
2007 }
2008 i++;
2009 }
2010 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2011 str = str_parms_to_str(reply);
2012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 str_parms_destroy(query);
2014 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002015 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 return str;
2017}
2018
2019static uint32_t out_get_latency(const struct audio_stream_out *stream)
2020{
2021 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023
Alexy Josephaa54c872014-12-03 02:46:47 -08002024 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002025 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002026 } else {
2027 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002029 }
2030
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302031 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002032 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033}
2034
2035static int out_set_volume(struct audio_stream_out *stream, float left,
2036 float right)
2037{
Eric Laurenta9024de2013-04-04 09:19:12 -07002038 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 int volume[2];
2040
Eric Laurenta9024de2013-04-04 09:19:12 -07002041 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2042 /* only take left channel into account: the API is for stereo anyway */
2043 out->muted = (left == 0.0f);
2044 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002045 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002046 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2047 /*
2048 * Set mute or umute on HDMI passthrough stream.
2049 * Only take left channel into account.
2050 * Mute is 0 and unmute 1
2051 */
2052 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2053 } else {
2054 char mixer_ctl_name[128];
2055 struct audio_device *adev = out->dev;
2056 struct mixer_ctl *ctl;
2057 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002058 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002060 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2061 "Compress Playback %d Volume", pcm_device_id);
2062 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2063 if (!ctl) {
2064 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2065 __func__, mixer_ctl_name);
2066 return -EINVAL;
2067 }
2068 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2069 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2070 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2071 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002073 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 return -ENOSYS;
2076}
2077
2078static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2079 size_t bytes)
2080{
2081 struct stream_out *out = (struct stream_out *)stream;
2082 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302083 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002084 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302087
Naresh Tanniru80659832014-06-04 18:17:56 +05302088 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002089 // increase written size during SSR to avoid mismatch
2090 // with the written frames count in AF
2091 if (!is_offload_usecase(out->usecase))
2092 out->written += bytes / (out->config.channels * sizeof(short));
2093
Naresh Tanniru80659832014-06-04 18:17:56 +05302094 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302095 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302096 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302097 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002098 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302099 //during SSR for compress usecase we should return error to flinger
2100 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2101 pthread_mutex_unlock(&out->lock);
2102 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302103 }
2104 }
2105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002107 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002108 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002109 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2110 ret = voice_extn_compress_voip_start_output_stream(out);
2111 else
2112 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002113 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002116 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 goto exit;
2118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302121 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2122 setChannelStatus(out, buffer, bytes);
2123 adev->mChannelStatusSet = true;
2124 }
2125
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002126 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002127 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002129 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2131 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302132 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2133 ALOGD("copl(%p):send next track params in gapless", out);
2134 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2135 out->send_next_track_params = false;
2136 out->is_compr_metadata_avail = false;
2137 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002138 }
2139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302141 if (ret < 0)
2142 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002143 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002144 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302145 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302147 } else if (-ENETRESET == ret) {
2148 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2149 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2150 pthread_mutex_unlock(&out->lock);
2151 out_standby(&out->stream.common);
2152 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002156 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 out->playback_started = 1;
2158 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002159
2160 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2161 popcount(out->channel_mask),
2162 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 }
2164 pthread_mutex_unlock(&out->lock);
2165 return ret;
2166 } else {
2167 if (out->pcm) {
2168 if (out->muted)
2169 memset((void *)buffer, 0, bytes);
2170 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002171 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2172 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2173 else
2174 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302175 if (ret < 0)
2176 ret = -errno;
2177 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002178 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 }
2181
2182exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302183 /* ToDo: There may be a corner case when SSR happens back to back during
2184 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302185 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302186 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302187 }
2188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 pthread_mutex_unlock(&out->lock);
2190
2191 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002192 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002193 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302194 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302195 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302196 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302197 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302198 out->standby = true;
2199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002201 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302202 out_get_sample_rate(&out->stream.common));
2203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 }
2205 return bytes;
2206}
2207
2208static int out_get_render_position(const struct audio_stream_out *stream,
2209 uint32_t *dsp_frames)
2210{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302212 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002213
2214 if (dsp_frames == NULL)
2215 return -EINVAL;
2216
2217 *dsp_frames = 0;
2218 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002219 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002220 pthread_mutex_lock(&out->lock);
2221 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302224 if (ret < 0)
2225 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 ALOGVV("%s rendered frames %d sample_rate %d",
2227 __func__, *dsp_frames, out->sample_rate);
2228 }
2229 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302230 if (-ENETRESET == ret) {
2231 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2232 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2233 return -EINVAL;
2234 } else if(ret < 0) {
2235 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2236 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302237 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2238 /*
2239 * Handle corner case where compress session is closed during SSR
2240 * and timestamp is queried
2241 */
2242 ALOGE(" ERROR: sound card not active, return error");
2243 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302244 } else {
2245 return 0;
2246 }
Zhou Song32a556e2015-05-05 10:46:56 +08002247 } else if (audio_is_linear_pcm(out->format)) {
2248 *dsp_frames = out->written;
2249 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 } else
2251 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252}
2253
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002254static int out_add_audio_effect(const struct audio_stream *stream __unused,
2255 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256{
2257 return 0;
2258}
2259
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002260static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2261 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262{
2263 return 0;
2264}
2265
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002266static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2267 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268{
2269 return -EINVAL;
2270}
2271
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002272static int out_get_presentation_position(const struct audio_stream_out *stream,
2273 uint64_t *frames, struct timespec *timestamp)
2274{
2275 struct stream_out *out = (struct stream_out *)stream;
2276 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002277 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002278
2279 pthread_mutex_lock(&out->lock);
2280
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002281 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002282 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302283 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002284 &out->sample_rate);
2285 ALOGVV("%s rendered frames %ld sample_rate %d",
2286 __func__, dsp_frames, out->sample_rate);
2287 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302288 if (ret < 0)
2289 ret = -errno;
2290 if (-ENETRESET == ret) {
2291 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2292 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2293 ret = -EINVAL;
2294 } else
2295 ret = 0;
2296
Eric Laurent949a0892013-09-20 09:20:13 -07002297 /* this is the best we can do */
2298 clock_gettime(CLOCK_MONOTONIC, timestamp);
2299 }
2300 } else {
2301 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002302 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002303 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2304 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002305 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002306 // This adjustment accounts for buffering after app processor.
2307 // It is based on estimated DSP latency per use case, rather than exact.
2308 signed_frames -=
2309 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2310
Eric Laurent949a0892013-09-20 09:20:13 -07002311 // It would be unusual for this value to be negative, but check just in case ...
2312 if (signed_frames >= 0) {
2313 *frames = signed_frames;
2314 ret = 0;
2315 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002316 }
2317 }
2318 }
2319
2320 pthread_mutex_unlock(&out->lock);
2321
2322 return ret;
2323}
2324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002325static int out_set_callback(struct audio_stream_out *stream,
2326 stream_callback_t callback, void *cookie)
2327{
2328 struct stream_out *out = (struct stream_out *)stream;
2329
2330 ALOGV("%s", __func__);
2331 pthread_mutex_lock(&out->lock);
2332 out->offload_callback = callback;
2333 out->offload_cookie = cookie;
2334 pthread_mutex_unlock(&out->lock);
2335 return 0;
2336}
2337
2338static int out_pause(struct audio_stream_out* stream)
2339{
2340 struct stream_out *out = (struct stream_out *)stream;
2341 int status = -ENOSYS;
2342 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002343 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002344 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 pthread_mutex_lock(&out->lock);
2346 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302347 struct audio_device *adev = out->dev;
2348 int snd_scard_state = get_snd_card_state(adev);
2349
2350 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2351 status = compress_pause(out->compr);
2352
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002354
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302355 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002356 audio_extn_dts_notify_playback_state(out->usecase, 0,
2357 out->sample_rate, popcount(out->channel_mask),
2358 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 }
2360 pthread_mutex_unlock(&out->lock);
2361 }
2362 return status;
2363}
2364
2365static int out_resume(struct audio_stream_out* stream)
2366{
2367 struct stream_out *out = (struct stream_out *)stream;
2368 int status = -ENOSYS;
2369 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002370 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002371 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 status = 0;
2373 pthread_mutex_lock(&out->lock);
2374 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302375 struct audio_device *adev = out->dev;
2376 int snd_scard_state = get_snd_card_state(adev);
2377
2378 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2379 status = compress_resume(out->compr);
2380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002382
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302383 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002384 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2385 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 }
2387 pthread_mutex_unlock(&out->lock);
2388 }
2389 return status;
2390}
2391
2392static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
2395 int status = -ENOSYS;
2396 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002397 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 pthread_mutex_lock(&out->lock);
2399 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2400 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2401 else
2402 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2403 pthread_mutex_unlock(&out->lock);
2404 }
2405 return status;
2406}
2407
2408static int out_flush(struct audio_stream_out* stream)
2409{
2410 struct stream_out *out = (struct stream_out *)stream;
2411 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002412 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002413 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 pthread_mutex_lock(&out->lock);
2415 stop_compressed_output_l(out);
2416 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002417 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418 return 0;
2419 }
2420 return -ENOSYS;
2421}
2422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423/** audio_stream_in implementation **/
2424static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2425{
2426 struct stream_in *in = (struct stream_in *)stream;
2427
2428 return in->config.rate;
2429}
2430
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002431static int in_set_sample_rate(struct audio_stream *stream __unused,
2432 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433{
2434 return -ENOSYS;
2435}
2436
2437static size_t in_get_buffer_size(const struct audio_stream *stream)
2438{
2439 struct stream_in *in = (struct stream_in *)stream;
2440
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002441 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2442 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002443 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2444 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002445
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002446 return in->config.period_size *
2447 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448}
2449
2450static uint32_t in_get_channels(const struct audio_stream *stream)
2451{
2452 struct stream_in *in = (struct stream_in *)stream;
2453
2454 return in->channel_mask;
2455}
2456
2457static audio_format_t in_get_format(const struct audio_stream *stream)
2458{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459 struct stream_in *in = (struct stream_in *)stream;
2460
2461 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462}
2463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002464static int in_set_format(struct audio_stream *stream __unused,
2465 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466{
2467 return -ENOSYS;
2468}
2469
2470static int in_standby(struct audio_stream *stream)
2471{
2472 struct stream_in *in = (struct stream_in *)stream;
2473 struct audio_device *adev = in->dev;
2474 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302475 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2476 stream, in->usecase, use_case_table[in->usecase]);
2477
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002478 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2479 /* Ignore standby in case of voip call because the voip input
2480 * stream is closed in adev_close_input_stream()
2481 */
2482 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2483 return status;
2484 }
2485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002487 if (!in->standby && in->is_st_session) {
2488 ALOGD("%s: sound trigger pcm stop lab", __func__);
2489 audio_extn_sound_trigger_stop_lab(in);
2490 in->standby = 1;
2491 }
2492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002494 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002496 if (in->pcm) {
2497 pcm_close(in->pcm);
2498 in->pcm = NULL;
2499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002501 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 }
2503 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002504 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 return status;
2506}
2507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002508static int in_dump(const struct audio_stream *stream __unused,
2509 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510{
2511 return 0;
2512}
2513
2514static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2515{
2516 struct stream_in *in = (struct stream_in *)stream;
2517 struct audio_device *adev = in->dev;
2518 struct str_parms *parms;
2519 char *str;
2520 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002521 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302523 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 parms = str_parms_create_str(kvpairs);
2525
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302526 if (!parms)
2527 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002529 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002530
2531 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2532 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 val = atoi(value);
2534 /* no audio source uses val == 0 */
2535 if ((in->source != val) && (val != 0)) {
2536 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002537 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2538 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2539 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2540 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002541 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002542 err = voice_extn_compress_voip_open_input_stream(in);
2543 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002544 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002545 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002546 }
2547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 }
2549 }
2550
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002551 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2552 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002554 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 in->device = val;
2556 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002557 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002558 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 }
2560 }
2561
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002562done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002564 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565
2566 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302567error:
Eric Laurent994a6932013-07-17 11:51:42 -07002568 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 return ret;
2570}
2571
2572static char* in_get_parameters(const struct audio_stream *stream,
2573 const char *keys)
2574{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 struct stream_in *in = (struct stream_in *)stream;
2576 struct str_parms *query = str_parms_create_str(keys);
2577 char *str;
2578 char value[256];
2579 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002580
2581 if (!query || !reply) {
2582 ALOGE("in_get_parameters: failed to create query or reply");
2583 return NULL;
2584 }
2585
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002586 ALOGV("%s: enter: keys - %s", __func__, keys);
2587
2588 voice_extn_in_get_parameters(in, query, reply);
2589
2590 str = str_parms_to_str(reply);
2591 str_parms_destroy(query);
2592 str_parms_destroy(reply);
2593
2594 ALOGV("%s: exit: returns - %s", __func__, str);
2595 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596}
2597
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002598static int in_set_gain(struct audio_stream_in *stream __unused,
2599 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 return 0;
2602}
2603
2604static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2605 size_t bytes)
2606{
2607 struct stream_in *in = (struct stream_in *)stream;
2608 struct audio_device *adev = in->dev;
2609 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302610 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302613
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002614 if (in->is_st_session) {
2615 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2616 /* Read from sound trigger HAL */
2617 audio_extn_sound_trigger_read(in, buffer, bytes);
2618 pthread_mutex_unlock(&in->lock);
2619 return bytes;
2620 }
2621
2622 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2623 ALOGD(" %s: sound card is not active/SSR state", __func__);
2624 ret= -EIO;;
2625 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302626 }
2627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002629 pthread_mutex_lock(&adev->lock);
2630 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2631 ret = voice_extn_compress_voip_start_input_stream(in);
2632 else
2633 ret = start_input_stream(in);
2634 pthread_mutex_unlock(&adev->lock);
2635 if (ret != 0) {
2636 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 }
2638 in->standby = 0;
2639 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640
2641 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002642 if (audio_extn_ssr_get_enabled() &&
2643 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002644 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002645 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2646 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002647 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2648 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002649 else
2650 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302651 if (ret < 0)
2652 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 }
2654
2655 /*
2656 * Instead of writing zeroes here, we could trust the hardware
2657 * to always provide zeroes when muted.
2658 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302659 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2660 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 memset(buffer, 0, bytes);
2662
2663exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302664 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302665 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002666 if (-ENETRESET == ret)
2667 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 pthread_mutex_unlock(&in->lock);
2670
2671 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302672 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302673 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302674 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302675 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302676 in->standby = true;
2677 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302678 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002680 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002681 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302682 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 }
2684 return bytes;
2685}
2686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002687static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688{
2689 return 0;
2690}
2691
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002692static int add_remove_audio_effect(const struct audio_stream *stream,
2693 effect_handle_t effect,
2694 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002696 struct stream_in *in = (struct stream_in *)stream;
2697 int status = 0;
2698 effect_descriptor_t desc;
2699
2700 status = (*effect)->get_descriptor(effect, &desc);
2701 if (status != 0)
2702 return status;
2703
2704 pthread_mutex_lock(&in->lock);
2705 pthread_mutex_lock(&in->dev->lock);
2706 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2707 in->enable_aec != enable &&
2708 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2709 in->enable_aec = enable;
2710 if (!in->standby)
2711 select_devices(in->dev, in->usecase);
2712 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002713 if (in->enable_ns != enable &&
2714 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2715 in->enable_ns = enable;
2716 if (!in->standby)
2717 select_devices(in->dev, in->usecase);
2718 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002719 pthread_mutex_unlock(&in->dev->lock);
2720 pthread_mutex_unlock(&in->lock);
2721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 return 0;
2723}
2724
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002725static int in_add_audio_effect(const struct audio_stream *stream,
2726 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727{
Eric Laurent994a6932013-07-17 11:51:42 -07002728 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002729 return add_remove_audio_effect(stream, effect, true);
2730}
2731
2732static int in_remove_audio_effect(const struct audio_stream *stream,
2733 effect_handle_t effect)
2734{
Eric Laurent994a6932013-07-17 11:51:42 -07002735 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002736 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737}
2738
2739static int adev_open_output_stream(struct audio_hw_device *dev,
2740 audio_io_handle_t handle,
2741 audio_devices_t devices,
2742 audio_output_flags_t flags,
2743 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002744 struct audio_stream_out **stream_out,
2745 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746{
2747 struct audio_device *adev = (struct audio_device *)dev;
2748 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002749 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002750 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302753
2754 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2755 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2756 ALOGE(" sound card is not active rejecting compress output open request");
2757 return -EINVAL;
2758 }
2759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2761
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302762 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2763 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2764 devices, flags, &out->stream);
2765
2766
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002767 if (!out) {
2768 return -ENOMEM;
2769 }
2770
Haynes Mathew George204045b2015-02-25 20:32:03 -08002771 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2772 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 if (devices == AUDIO_DEVICE_NONE)
2775 devices = AUDIO_DEVICE_OUT_SPEAKER;
2776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 out->flags = flags;
2778 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002779 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002780 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 out->sample_rate = config->sample_rate;
2782 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2783 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002784 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002785 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002786 out->non_blocking = 0;
2787 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002789 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2790 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002791 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2792 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2793
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002794 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002795 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2796 ret = read_hdmi_channel_masks(out);
2797
2798 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2799 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002800 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002801 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002802 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002803
2804 if (config->sample_rate == 0)
2805 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2806 if (config->channel_mask == 0)
2807 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2808
2809 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2812 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002814 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002816 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2817 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002818 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002819 ret = voice_extn_compress_voip_open_output_stream(out);
2820 if (ret != 0) {
2821 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2822 __func__, ret);
2823 goto error_open;
2824 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2826 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2827 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2828 ALOGE("%s: Unsupported Offload information", __func__);
2829 ret = -EINVAL;
2830 goto error_open;
2831 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002832
2833 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2834 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2835 ALOGV("read and update_pass through formats");
2836 ret = audio_extn_dolby_update_passt_formats(adev, out);
2837 if(ret != 0) {
2838 goto error_open;
2839 }
2840 if(config->offload_info.format == 0)
2841 config->offload_info.format = out->supported_formats[0];
2842 }
2843
Mingming Yin90310102013-11-13 16:57:00 -08002844 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002845 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 ALOGE("%s: Unsupported audio format", __func__);
2847 ret = -EINVAL;
2848 goto error_open;
2849 }
2850
2851 out->compr_config.codec = (struct snd_codec *)
2852 calloc(1, sizeof(struct snd_codec));
2853
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002854 if (!out->compr_config.codec) {
2855 ret = -ENOMEM;
2856 goto error_open;
2857 }
2858
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002859 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 if (config->offload_info.channel_mask)
2861 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002862 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002864 config->offload_info.channel_mask = config->channel_mask;
2865 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002866 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867 out->sample_rate = config->offload_info.sample_rate;
2868
2869 out->stream.set_callback = out_set_callback;
2870 out->stream.pause = out_pause;
2871 out->stream.resume = out_resume;
2872 out->stream.drain = out_drain;
2873 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002874 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002876 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002877 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002878 audio_extn_dolby_get_snd_codec_id(adev, out,
2879 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002880 else
2881 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002883 if (audio_is_offload_pcm(config->offload_info.format)) {
2884 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002885 platform_get_pcm_offload_buffer_size(&config->offload_info);
2886 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2887 out->compr_config.fragment_size =
2888 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002889 } else {
2890 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002891 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002892 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2894 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002895 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 out->compr_config.codec->bit_rate =
2897 config->offload_info.bit_rate;
2898 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002899 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002901 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902 /*TODO: Do we need to change it for passthrough */
2903 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904
Mingming Yin3ee55c62014-08-04 14:23:35 -07002905 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2906 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2908 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002909 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002910 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2911
Mingming Yin3ee55c62014-08-04 14:23:35 -07002912 if (out->bit_width == 24) {
2913 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2914 }
2915
Amit Shekhar6f461b12014-08-01 14:52:58 -07002916 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002917 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2920 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002921
Alexy Josephaa54c872014-12-03 02:46:47 -08002922 if (config->offload_info.use_small_bufs) {
2923 //this flag is set from framework only if its for PCM formats
2924 //no need to check for PCM format again
2925 out->non_blocking = 0;
2926 out->use_small_bufs = true;
2927 ALOGI("Keep write blocking for small buff: non_blockling %d",
2928 out->non_blocking);
2929 }
2930
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002931 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302932 out->send_next_track_params = false;
2933 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002934 out->offload_state = OFFLOAD_STATE_IDLE;
2935 out->playback_started = 0;
2936
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002937 audio_extn_dts_create_state_notifier_node(out->usecase);
2938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 create_offload_callback_thread(out);
2940 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2941 __func__, config->offload_info.version,
2942 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002943 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002944 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002945 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2946 ret = voice_check_and_set_incall_music_usecase(adev, out);
2947 if (ret != 0) {
2948 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2949 __func__, ret);
2950 goto error_open;
2951 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002952 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2953 if (config->sample_rate == 0)
2954 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2955 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2956 config->sample_rate != 8000) {
2957 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2958 ret = -EINVAL;
2959 goto error_open;
2960 }
2961 out->sample_rate = config->sample_rate;
2962 out->config.rate = config->sample_rate;
2963 if (config->format == AUDIO_FORMAT_DEFAULT)
2964 config->format = AUDIO_FORMAT_PCM_16_BIT;
2965 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2966 config->format = AUDIO_FORMAT_PCM_16_BIT;
2967 ret = -EINVAL;
2968 goto error_open;
2969 }
2970 out->format = config->format;
2971 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2972 out->config = pcm_config_afe_proxy_playback;
2973 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002974 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002975 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2977 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002979 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2980 format = AUDIO_FORMAT_PCM_16_BIT;
2981 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2982 out->config = pcm_config_deep_buffer;
2983 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002984 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002985 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002986 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002987 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002988 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002989 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 }
2991
Amit Shekhar1d896042014-10-03 13:16:09 -07002992 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2993 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002994 /* TODO remove this hardcoding and check why width is zero*/
2995 if (out->bit_width == 0)
2996 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002997 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2998 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002999 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303000 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003001 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3002 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3003 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003004 if(adev->primary_output == NULL)
3005 adev->primary_output = out;
3006 else {
3007 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003008 ret = -EEXIST;
3009 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003010 }
3011 }
3012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 /* Check if this usecase is already existing */
3014 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003015 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3016 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003019 ret = -EEXIST;
3020 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 }
3022 pthread_mutex_unlock(&adev->lock);
3023
3024 out->stream.common.get_sample_rate = out_get_sample_rate;
3025 out->stream.common.set_sample_rate = out_set_sample_rate;
3026 out->stream.common.get_buffer_size = out_get_buffer_size;
3027 out->stream.common.get_channels = out_get_channels;
3028 out->stream.common.get_format = out_get_format;
3029 out->stream.common.set_format = out_set_format;
3030 out->stream.common.standby = out_standby;
3031 out->stream.common.dump = out_dump;
3032 out->stream.common.set_parameters = out_set_parameters;
3033 out->stream.common.get_parameters = out_get_parameters;
3034 out->stream.common.add_audio_effect = out_add_audio_effect;
3035 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3036 out->stream.get_latency = out_get_latency;
3037 out->stream.set_volume = out_set_volume;
3038 out->stream.write = out_write;
3039 out->stream.get_render_position = out_get_render_position;
3040 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003041 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003044 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003045 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046
3047 config->format = out->stream.common.get_format(&out->stream.common);
3048 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3049 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3050
3051 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303052 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3053 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003054
3055 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3056 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3057 popcount(out->channel_mask), out->playback_started);
3058
Eric Laurent994a6932013-07-17 11:51:42 -07003059 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003061
3062error_open:
3063 free(out);
3064 *stream_out = NULL;
3065 ALOGD("%s: exit: ret %d", __func__, ret);
3066 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067}
3068
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003069static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 struct audio_stream_out *stream)
3071{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 struct stream_out *out = (struct stream_out *)stream;
3073 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003075
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303076 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3077
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303079 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003080 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303081 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 if(ret != 0)
3083 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3084 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003085 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003086 out_standby(&stream->common);
3087
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003088 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003089 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003091 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 if (out->compr_config.codec != NULL)
3093 free(out->compr_config.codec);
3094 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003095
3096 if (adev->voice_tx_output == out)
3097 adev->voice_tx_output = NULL;
3098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 pthread_cond_destroy(&out->cond);
3100 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003102 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103}
3104
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003105static void close_compress_sessions(struct audio_device *adev)
3106{
Mingming Yin7b762e72015-03-04 13:47:32 -08003107 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303108 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003109 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003110 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303111
3112 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003113 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303114 if (is_offload_usecase(usecase->id)) {
3115 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003116 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3117 out = usecase->stream.out;
3118 pthread_mutex_unlock(&adev->lock);
3119 out_standby(&out->stream.common);
3120 pthread_mutex_lock(&adev->lock);
3121 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303122 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003123 }
3124 pthread_mutex_unlock(&adev->lock);
3125}
3126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3128{
3129 struct audio_device *adev = (struct audio_device *)dev;
3130 struct str_parms *parms;
3131 char *str;
3132 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003133 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003134 int ret;
3135 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003137 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303140 if (!parms)
3141 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003142 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3143 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303146 struct listnode *node;
3147 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303148 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303149 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003150 //close compress sessions on OFFLINE status
3151 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303152 } else if (strstr(snd_card_status, "ONLINE")) {
3153 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303154 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303155 if (!platform_is_acdb_initialized(adev->platform)) {
3156 ret = platform_acdb_init(adev->platform);
3157 if(ret)
3158 ALOGE("acdb initialization is failed");
3159
3160 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162 }
3163
3164 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003165 status = voice_set_parameters(adev, parms);
3166 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003167 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003169 status = platform_set_parameters(adev->platform, parms);
3170 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003171 goto done;
3172
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003173 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3174 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003175 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3177 adev->bluetooth_nrec = true;
3178 else
3179 adev->bluetooth_nrec = false;
3180 }
3181
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3183 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3185 adev->screen_off = false;
3186 else
3187 adev->screen_off = true;
3188 }
3189
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003190 ret = str_parms_get_int(parms, "rotation", &val);
3191 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003192 bool reverse_speakers = false;
3193 switch(val) {
3194 // FIXME: note that the code below assumes that the speakers are in the correct placement
3195 // relative to the user when the device is rotated 90deg from its default rotation. This
3196 // assumption is device-specific, not platform-specific like this code.
3197 case 270:
3198 reverse_speakers = true;
3199 break;
3200 case 0:
3201 case 90:
3202 case 180:
3203 break;
3204 default:
3205 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003207 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003208 if (status == 0) {
3209 if (adev->speaker_lr_swap != reverse_speakers) {
3210 adev->speaker_lr_swap = reverse_speakers;
3211 // only update the selected device if there is active pcm playback
3212 struct audio_usecase *usecase;
3213 struct listnode *node;
3214 list_for_each(node, &adev->usecase_list) {
3215 usecase = node_to_item(node, struct audio_usecase, list);
3216 if (usecase->type == PCM_PLAYBACK) {
3217 select_devices(adev, usecase->id);
3218 break;
3219 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003220 }
3221 }
3222 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003223 }
3224
Mingming Yin514a8bc2014-07-29 15:22:21 -07003225 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3226 if (ret >= 0) {
3227 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3228 adev->bt_wb_speech_enabled = true;
3229 else
3230 adev->bt_wb_speech_enabled = false;
3231 }
3232
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003233 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3234 if (ret >= 0) {
3235 val = atoi(value);
3236 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3237 ALOGV("cache new edid");
3238 platform_cache_edid(adev->platform);
3239 }
3240 }
3241
3242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3243 if (ret >= 0) {
3244 val = atoi(value);
3245 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3246 ALOGV("invalidate cached edid");
3247 platform_invalidate_edid(adev->platform);
3248 }
3249 }
3250
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003251 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003252
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003253done:
3254 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003255 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303256error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003257 ALOGV("%s: exit with code(%d)", __func__, status);
3258 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259}
3260
3261static char* adev_get_parameters(const struct audio_hw_device *dev,
3262 const char *keys)
3263{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003264 struct audio_device *adev = (struct audio_device *)dev;
3265 struct str_parms *reply = str_parms_create();
3266 struct str_parms *query = str_parms_create_str(keys);
3267 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303268 char value[256] = {0};
3269 int ret = 0;
3270
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003271 if (!query || !reply) {
3272 ALOGE("adev_get_parameters: failed to create query or reply");
3273 return NULL;
3274 }
3275
Naresh Tannirud7205b62014-06-20 02:54:48 +05303276 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3277 sizeof(value));
3278 if (ret >=0) {
3279 int val = 1;
3280 pthread_mutex_lock(&adev->snd_card_status.lock);
3281 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3282 val = 0;
3283 pthread_mutex_unlock(&adev->snd_card_status.lock);
3284 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3285 goto exit;
3286 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003287
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003288 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003289 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003290 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003291 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303292 pthread_mutex_unlock(&adev->lock);
3293
Naresh Tannirud7205b62014-06-20 02:54:48 +05303294exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003295 str = str_parms_to_str(reply);
3296 str_parms_destroy(query);
3297 str_parms_destroy(reply);
3298
3299 ALOGV("%s: exit: returns - %s", __func__, str);
3300 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301}
3302
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003303static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304{
3305 return 0;
3306}
3307
3308static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3309{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003310 int ret;
3311 struct audio_device *adev = (struct audio_device *)dev;
3312 pthread_mutex_lock(&adev->lock);
3313 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003314 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003315 pthread_mutex_unlock(&adev->lock);
3316 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003319static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3320 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
3322 return -ENOSYS;
3323}
3324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003325static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3326 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327{
3328 return -ENOSYS;
3329}
3330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003331static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3332 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
3334 return -ENOSYS;
3335}
3336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003337static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3338 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339{
3340 return -ENOSYS;
3341}
3342
3343static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3344{
3345 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 pthread_mutex_lock(&adev->lock);
3348 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003349 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003351 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3352 voice_is_in_call(adev)) {
3353 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303354 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355 adev->current_call_output = NULL;
3356 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
3358 pthread_mutex_unlock(&adev->lock);
3359 return 0;
3360}
3361
3362static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3363{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003364 int ret;
3365
3366 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003367 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003368 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3369 pthread_mutex_unlock(&adev->lock);
3370
3371 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372}
3373
3374static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3375{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003376 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 return 0;
3378}
3379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003380static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 const struct audio_config *config)
3382{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003383 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003385 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3386 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387}
3388
3389static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003390 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 audio_devices_t devices,
3392 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003393 struct audio_stream_in **stream_in,
3394 audio_input_flags_t flags __unused,
3395 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003396 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397{
3398 struct audio_device *adev = (struct audio_device *)dev;
3399 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003400 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003401 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003402 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 *stream_in = NULL;
3405 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3406 return -EINVAL;
3407
3408 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003409
3410 if (!in) {
3411 ALOGE("failed to allocate input stream");
3412 return -ENOMEM;
3413 }
3414
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303415 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003416 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3417 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003419 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 in->stream.common.get_sample_rate = in_get_sample_rate;
3422 in->stream.common.set_sample_rate = in_set_sample_rate;
3423 in->stream.common.get_buffer_size = in_get_buffer_size;
3424 in->stream.common.get_channels = in_get_channels;
3425 in->stream.common.get_format = in_get_format;
3426 in->stream.common.set_format = in_set_format;
3427 in->stream.common.standby = in_standby;
3428 in->stream.common.dump = in_dump;
3429 in->stream.common.set_parameters = in_set_parameters;
3430 in->stream.common.get_parameters = in_get_parameters;
3431 in->stream.common.add_audio_effect = in_add_audio_effect;
3432 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3433 in->stream.set_gain = in_set_gain;
3434 in->stream.read = in_read;
3435 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3436
3437 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003438 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 in->standby = 1;
3441 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003442 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443
3444 /* Update config params with the requested sample rate and channels */
3445 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003446 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3447 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3448 is_low_latency = true;
3449#if LOW_LATENCY_CAPTURE_USE_CASE
3450 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3451#endif
3452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003455 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003457 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303458 if (adev->mode != AUDIO_MODE_IN_CALL) {
3459 ret = -EINVAL;
3460 goto err_open;
3461 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 if (config->sample_rate == 0)
3463 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3464 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3465 config->sample_rate != 8000) {
3466 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3467 ret = -EINVAL;
3468 goto err_open;
3469 }
3470 if (config->format == AUDIO_FORMAT_DEFAULT)
3471 config->format = AUDIO_FORMAT_PCM_16_BIT;
3472 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3473 config->format = AUDIO_FORMAT_PCM_16_BIT;
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477
3478 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3479 in->config = pcm_config_afe_proxy_record;
3480 in->config.channels = channel_count;
3481 in->config.rate = config->sample_rate;
3482 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003483 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003484 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003485 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3486 ret = -EINVAL;
3487 goto err_open;
3488 }
3489 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003490 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491 }
Mingming Yine62d7842013-10-25 16:26:03 -07003492 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003493 audio_extn_compr_cap_format_supported(config->format) &&
3494 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003495 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003496 } else {
3497 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003498 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 buffer_size = get_input_buffer_size(config->sample_rate,
3500 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003501 channel_count,
3502 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003503 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003504 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3505 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3506 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3507 (in->config.rate == 8000 || in->config.rate == 16000) &&
3508 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3509 voice_extn_compress_voip_open_input_stream(in);
3510 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003513 /* This stream could be for sound trigger lab,
3514 get sound trigger pcm if present */
3515 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303516 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003519 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003520 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
3522err_open:
3523 free(in);
3524 *stream_in = NULL;
3525 return ret;
3526}
3527
3528static void adev_close_input_stream(struct audio_hw_device *dev,
3529 struct audio_stream_in *stream)
3530{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003531 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003532 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003533 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303534
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303535 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003536
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303537 /* Disable echo reference while closing input stream */
3538 platform_set_echo_reference(adev->platform, false);
3539
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303541 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003542 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303543 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003544 if (ret != 0)
3545 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3546 __func__, ret);
3547 } else
3548 in_standby(&stream->common);
3549
Mingming Yin7b762e72015-03-04 13:47:32 -08003550 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003551 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003552 audio_extn_ssr_deinit();
3553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554
Mingming Yine62d7842013-10-25 16:26:03 -07003555 if(audio_extn_compr_cap_enabled() &&
3556 audio_extn_compr_cap_format_supported(in->config.format))
3557 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003558
3559 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 return;
3561}
3562
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003563static int adev_dump(const audio_hw_device_t *device __unused,
3564 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565{
3566 return 0;
3567}
3568
3569static int adev_close(hw_device_t *device)
3570{
3571 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003572
3573 if (!adev)
3574 return 0;
3575
3576 pthread_mutex_lock(&adev_init_lock);
3577
3578 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003579 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003580 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003581 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003582 audio_route_free(adev->audio_route);
3583 free(adev->snd_dev_ref_cnt);
3584 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003585 free(device);
3586 adev = NULL;
3587 }
3588 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 return 0;
3590}
3591
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003592/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3593 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3594 * just that it _might_ work.
3595 */
3596static int period_size_is_plausible_for_low_latency(int period_size)
3597{
3598 switch (period_size) {
3599 case 160:
3600 case 240:
3601 case 320:
3602 case 480:
3603 return 1;
3604 default:
3605 return 0;
3606 }
3607}
3608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609static int adev_open(const hw_module_t *module, const char *name,
3610 hw_device_t **device)
3611{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003612 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003614 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3616
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003617 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003618 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003619 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003620 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003621 ALOGD("%s: returning existing instance of adev", __func__);
3622 ALOGD("%s: exit", __func__);
3623 pthread_mutex_unlock(&adev_init_lock);
3624 return 0;
3625 }
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 adev = calloc(1, sizeof(struct audio_device));
3628
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003629 if (!adev) {
3630 pthread_mutex_unlock(&adev_init_lock);
3631 return -ENOMEM;
3632 }
3633
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003634 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3637 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3638 adev->device.common.module = (struct hw_module_t *)module;
3639 adev->device.common.close = adev_close;
3640
3641 adev->device.init_check = adev_init_check;
3642 adev->device.set_voice_volume = adev_set_voice_volume;
3643 adev->device.set_master_volume = adev_set_master_volume;
3644 adev->device.get_master_volume = adev_get_master_volume;
3645 adev->device.set_master_mute = adev_set_master_mute;
3646 adev->device.get_master_mute = adev_get_master_mute;
3647 adev->device.set_mode = adev_set_mode;
3648 adev->device.set_mic_mute = adev_set_mic_mute;
3649 adev->device.get_mic_mute = adev_get_mic_mute;
3650 adev->device.set_parameters = adev_set_parameters;
3651 adev->device.get_parameters = adev_get_parameters;
3652 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3653 adev->device.open_output_stream = adev_open_output_stream;
3654 adev->device.close_output_stream = adev_close_output_stream;
3655 adev->device.open_input_stream = adev_open_input_stream;
3656 adev->device.close_input_stream = adev_close_input_stream;
3657 adev->device.dump = adev_dump;
3658
3659 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003661 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003662 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003665 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003666 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003667 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003668 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003669 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003670 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003671 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303672 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303673
3674 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3675 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003677 adev->platform = platform_init(adev);
3678 if (!adev->platform) {
3679 free(adev->snd_dev_ref_cnt);
3680 free(adev);
3681 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3682 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003683 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003684 return -EINVAL;
3685 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003686
Naresh Tanniru4c630392014-05-12 01:05:52 +05303687 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3688
Eric Laurentc4aef752013-09-12 17:45:53 -07003689 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3690 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3691 if (adev->visualizer_lib == NULL) {
3692 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3693 } else {
3694 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3695 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003696 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003697 "visualizer_hal_start_output");
3698 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003699 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003700 "visualizer_hal_stop_output");
3701 }
3702 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003703 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003704 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003705
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003706 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3707 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3708 if (adev->offload_effects_lib == NULL) {
3709 ALOGE("%s: DLOPEN failed for %s", __func__,
3710 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3711 } else {
3712 ALOGV("%s: DLOPEN successful for %s", __func__,
3713 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3714 adev->offload_effects_start_output =
3715 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3716 "offload_effects_bundle_hal_start_output");
3717 adev->offload_effects_stop_output =
3718 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3719 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003720 adev->offload_effects_set_hpx_state =
3721 (int (*)(bool))dlsym(adev->offload_effects_lib,
3722 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003723 }
3724 }
3725
Mingming Yin514a8bc2014-07-29 15:22:21 -07003726 adev->bt_wb_speech_enabled = false;
3727
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003728 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 *device = &adev->device.common;
3730
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003731 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3732 &adev->streams_output_cfg_list);
3733
Kiran Kandi910e1862013-10-29 13:29:42 -07003734 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003735
3736 char value[PROPERTY_VALUE_MAX];
3737 int trial;
3738 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3739 trial = atoi(value);
3740 if (period_size_is_plausible_for_low_latency(trial)) {
3741 pcm_config_low_latency.period_size = trial;
3742 pcm_config_low_latency.start_threshold = trial / 4;
3743 pcm_config_low_latency.avail_min = trial / 4;
3744 configured_low_latency_capture_period_size = trial;
3745 }
3746 }
3747 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3748 trial = atoi(value);
3749 if (period_size_is_plausible_for_low_latency(trial)) {
3750 configured_low_latency_capture_period_size = trial;
3751 }
3752 }
3753
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003754 pthread_mutex_unlock(&adev_init_lock);
3755
Eric Laurent994a6932013-07-17 11:51:42 -07003756 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 return 0;
3758}
3759
3760static struct hw_module_methods_t hal_module_methods = {
3761 .open = adev_open,
3762};
3763
3764struct audio_module HAL_MODULE_INFO_SYM = {
3765 .common = {
3766 .tag = HARDWARE_MODULE_TAG,
3767 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3768 .hal_api_version = HARDWARE_HAL_API_VERSION,
3769 .id = AUDIO_HARDWARE_MODULE_ID,
3770 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003771 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 .methods = &hal_module_methods,
3773 },
3774};