blob: 435138df9aa9aebf2b376441995a22a9ac375579 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800489 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200567 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568 audio_extn_sound_trigger_update_device_status(snd_device,
569 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530570 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800571 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 return 0;
575}
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577static void check_usecases_codec_backend(struct audio_device *adev,
578 struct audio_usecase *uc_info,
579 snd_device_t snd_device)
580{
581 struct listnode *node;
582 struct audio_usecase *usecase;
583 bool switch_device[AUDIO_USECASE_MAX];
584 int i, num_uc_to_switch = 0;
585
586 /*
587 * This function is to make sure that all the usecases that are active on
588 * the hardware codec backend are always routed to any one device that is
589 * handled by the hardware codec.
590 * For example, if low-latency and deep-buffer usecases are currently active
591 * on speaker and out_set_parameters(headset) is received on low-latency
592 * output, then we have to make sure deep-buffer is also switched to headset,
593 * because of the limitation that both the devices cannot be enabled
594 * at the same time as they share the same backend.
595 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700596 /*
597 * This call is to check if we need to force routing for a particular stream
598 * If there is a backend configuration change for the device when a
599 * new stream starts, then ADM needs to be closed and re-opened with the new
600 * configuraion. This call check if we need to re-route all the streams
601 * associated with the backend. Touch tone + 24 bit playback.
602 */
603 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605 /* Disable all the usecases on the shared backend other than the
606 specified usecase */
607 for (i = 0; i < AUDIO_USECASE_MAX; i++)
608 switch_device[i] = false;
609
610 list_for_each(node, &adev->usecase_list) {
611 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800612 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700614 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
616 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
617 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700618 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700619 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 switch_device[usecase->id] = true;
621 num_uc_to_switch++;
622 }
623 }
624
625 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700626 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530628 /* Make sure the previous devices to be disabled first and then enable the
629 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 list_for_each(node, &adev->usecase_list) {
631 usecase = node_to_item(node, struct audio_usecase, list);
632 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700633 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 }
635 }
636
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
639 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700640 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700641 }
642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644 /* Re-route all the usecases on the shared backend other than the
645 specified usecase to new snd devices */
646 list_for_each(node, &adev->usecase_list) {
647 usecase = node_to_item(node, struct audio_usecase, list);
648 /* Update the out_snd_device only before enabling the audio route */
649 if (switch_device[usecase->id] ) {
650 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800651 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530652 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653 }
654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 }
656}
657
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700658static void check_and_route_capture_usecases(struct audio_device *adev,
659 struct audio_usecase *uc_info,
660 snd_device_t snd_device)
661{
662 struct listnode *node;
663 struct audio_usecase *usecase;
664 bool switch_device[AUDIO_USECASE_MAX];
665 int i, num_uc_to_switch = 0;
666
667 /*
668 * This function is to make sure that all the active capture usecases
669 * are always routed to the same input sound device.
670 * For example, if audio-record and voice-call usecases are currently
671 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
672 * is received for voice call then we have to make sure that audio-record
673 * usecase is also switched to earpiece i.e. voice-dmic-ef,
674 * because of the limitation that two devices cannot be enabled
675 * at the same time if they share the same backend.
676 */
677 for (i = 0; i < AUDIO_USECASE_MAX; i++)
678 switch_device[i] = false;
679
680 list_for_each(node, &adev->usecase_list) {
681 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800682 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700684 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530685 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700686 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700687 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
688 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700689 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700691 switch_device[usecase->id] = true;
692 num_uc_to_switch++;
693 }
694 }
695
696 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700697 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700698
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530699 /* Make sure the previous devices to be disabled first and then enable the
700 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 list_for_each(node, &adev->usecase_list) {
702 usecase = node_to_item(node, struct audio_usecase, list);
703 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700704 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800705 }
706 }
707
708 list_for_each(node, &adev->usecase_list) {
709 usecase = node_to_item(node, struct audio_usecase, list);
710 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 }
713 }
714
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700715 /* Re-route all the usecases on the shared backend other than the
716 specified usecase to new snd devices */
717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
719 /* Update the in_snd_device only before enabling the audio route */
720 if (switch_device[usecase->id] ) {
721 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800722 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530723 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 }
725 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700726 }
727}
728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800729/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700730static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800731{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700732 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700733 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734
735 switch (channels) {
736 /*
737 * Do not handle stereo output in Multi-channel cases
738 * Stereo case is handled in normal playback path
739 */
740 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700741 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
742 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
743 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
744 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
745 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
746 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747 break;
748 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700749 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
750 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
751 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
752 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
753 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800756 break;
757 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700758 ALOGE("HDMI does not support multi channel playback");
759 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 break;
761 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700762 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763}
764
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800765audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
766 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700767{
768 struct audio_usecase *usecase;
769 struct listnode *node;
770
771 list_for_each(node, &adev->usecase_list) {
772 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800773 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700774 ALOGV("%s: usecase id %d", __func__, usecase->id);
775 return usecase->id;
776 }
777 }
778 return USECASE_INVALID;
779}
780
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700781struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700782 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783{
784 struct audio_usecase *usecase;
785 struct listnode *node;
786
787 list_for_each(node, &adev->usecase_list) {
788 usecase = node_to_item(node, struct audio_usecase, list);
789 if (usecase->id == uc_id)
790 return usecase;
791 }
792 return NULL;
793}
794
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800797 snd_device_t out_snd_device = SND_DEVICE_NONE;
798 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 struct audio_usecase *usecase = NULL;
800 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800801 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800802 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800803 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800804 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700807 usecase = get_usecase_from_list(adev, uc_id);
808 if (usecase == NULL) {
809 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
810 return -EINVAL;
811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800814 (usecase->type == VOIP_CALL) ||
815 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700816 out_snd_device = platform_get_output_snd_device(adev->platform,
817 usecase->stream.out->devices);
818 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 usecase->devices = usecase->stream.out->devices;
820 } else {
821 /*
822 * If the voice call is active, use the sound devices of voice call usecase
823 * so that it would not result any device switch. All the usecases will
824 * be switched to new device when select_devices() is called for voice call
825 * usecase. This is to avoid switching devices for voice call when
826 * check_usecases_codec_backend() is called below.
827 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700828 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700829 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800830 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700831 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
832 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 in_snd_device = vc_usecase->in_snd_device;
834 out_snd_device = vc_usecase->out_snd_device;
835 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800836 } else if (voice_extn_compress_voip_is_active(adev)) {
837 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700838 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530839 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700840 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800841 in_snd_device = voip_usecase->in_snd_device;
842 out_snd_device = voip_usecase->out_snd_device;
843 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800844 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800845 hfp_ucid = audio_extn_hfp_get_usecase();
846 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700847 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800848 in_snd_device = hfp_usecase->in_snd_device;
849 out_snd_device = hfp_usecase->out_snd_device;
850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 }
852 if (usecase->type == PCM_PLAYBACK) {
853 usecase->devices = usecase->stream.out->devices;
854 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700855 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700856 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700858 if (usecase->stream.out == adev->primary_output &&
859 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800860 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
861 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700862 select_devices(adev, adev->active_input->usecase);
863 }
864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 } else if (usecase->type == PCM_CAPTURE) {
866 usecase->devices = usecase->stream.in->device;
867 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700869 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530870 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
871 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
872 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
873 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700874 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800875 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700876 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
877 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700878 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700879 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 }
883
884 if (out_snd_device == usecase->out_snd_device &&
885 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800886 return 0;
887 }
888
sangwoobc677242013-08-08 16:53:43 +0900889 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700890 out_snd_device, platform_get_snd_device_name(out_snd_device),
891 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 /*
894 * Limitation: While in call, to do a device switch we need to disable
895 * and enable both RX and TX devices though one of them is same as current
896 * device.
897 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700898 if ((usecase->type == VOICE_CALL) &&
899 (usecase->in_snd_device != SND_DEVICE_NONE) &&
900 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800902 }
903
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 /* Disable current sound devices */
905 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700906 disable_audio_route(adev, usecase);
907 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 }
909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700911 disable_audio_route(adev, usecase);
912 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 }
914
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800915 /* Applicable only on the targets that has external modem.
916 * New device information should be sent to modem before enabling
917 * the devices to reduce in-call device switch time.
918 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700919 if ((usecase->type == VOICE_CALL) &&
920 (usecase->in_snd_device != SND_DEVICE_NONE) &&
921 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800922 status = platform_switch_voice_call_enable_device_config(adev->platform,
923 out_snd_device,
924 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700925 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /* Enable new sound devices */
928 if (out_snd_device != SND_DEVICE_NONE) {
929 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
930 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700931 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 }
933
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 if (in_snd_device != SND_DEVICE_NONE) {
935 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700936 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700938
Avinash Vaish71a8b972014-07-24 15:36:33 +0530939 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700940 status = platform_switch_voice_call_device_post(adev->platform,
941 out_snd_device,
942 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530943 enable_audio_route_for_voice_usecases(adev, usecase);
944 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800945
sangwoo170731f2013-06-08 15:36:36 +0900946 usecase->in_snd_device = in_snd_device;
947 usecase->out_snd_device = out_snd_device;
948
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530949 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700950 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530951 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700952 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530953 usecase->stream.out->flags,
954 usecase->stream.out->format,
955 usecase->stream.out->sample_rate,
956 usecase->stream.out->bit_width,
Manish Dewanganf48adb42015-05-27 10:17:41 +0530957 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530958 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700959 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530960 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700961
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900963
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800964 /* Applicable only on the targets that has external modem.
965 * Enable device command should be sent to modem only after
966 * enabling voice call mixer controls
967 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700968 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800969 status = platform_switch_voice_call_usecase_route_post(adev->platform,
970 out_snd_device,
971 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530972 ALOGD("%s: done",__func__);
973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974 return status;
975}
976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977static int stop_input_stream(struct stream_in *in)
978{
979 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980 struct audio_usecase *uc_info;
981 struct audio_device *adev = in->dev;
982
Eric Laurentc8400632013-02-14 19:04:54 -0800983 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
Eric Laurent994a6932013-07-17 11:51:42 -0700985 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987 uc_info = get_usecase_from_list(adev, in->usecase);
988 if (uc_info == NULL) {
989 ALOGE("%s: Could not find the usecase (%d) in the list",
990 __func__, in->usecase);
991 return -EINVAL;
992 }
993
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800994 /* Close in-call recording streams */
995 voice_check_and_stop_incall_rec_usecase(adev, in);
996
Eric Laurent150dbfe2013-02-27 14:31:02 -0800997 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999
1000 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001001 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001003 list_remove(&uc_info->list);
1004 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005
Eric Laurent994a6932013-07-17 11:51:42 -07001006 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 return ret;
1008}
1009
1010int start_input_stream(struct stream_in *in)
1011{
1012 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001013 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 struct audio_usecase *uc_info;
1015 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301016 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017
Mingming Yine62d7842013-10-25 16:26:03 -07001018 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301019 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1020 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001021
Naresh Tanniru80659832014-06-04 18:17:56 +05301022
1023 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301024 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301025 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301026 goto error_config;
1027 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301028
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001029 /* Check if source matches incall recording usecase criteria */
1030 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1031 if (ret)
1032 goto error_config;
1033 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001034 ALOGD("%s: Updated usecase(%d: %s)",
1035 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001036
Eric Laurentb23d5282013-05-14 15:27:20 -07001037 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 if (in->pcm_device_id < 0) {
1039 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1040 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001041 ret = -EINVAL;
1042 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044
1045 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001047
1048 if (!uc_info) {
1049 ret = -ENOMEM;
1050 goto error_config;
1051 }
1052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053 uc_info->id = in->usecase;
1054 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001055 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 uc_info->devices = in->device;
1057 uc_info->in_snd_device = SND_DEVICE_NONE;
1058 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001060 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301061 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Eric Laurentc8400632013-02-14 19:04:54 -08001064 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001065 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1066
1067 unsigned int flags = PCM_IN;
1068 unsigned int pcm_open_retry_count = 0;
1069
1070 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1071 flags |= PCM_MMAP | PCM_NOIRQ;
1072 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1073 }
1074
1075 while (1) {
1076 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1077 flags, &in->config);
1078 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1079 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1080 if (in->pcm != NULL) {
1081 pcm_close(in->pcm);
1082 in->pcm = NULL;
1083 }
1084 if (pcm_open_retry_count-- == 0) {
1085 ret = -EIO;
1086 goto error_open;
1087 }
1088 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1089 continue;
1090 }
1091 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301093 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301094
Eric Laurent994a6932013-07-17 11:51:42 -07001095 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001096 return ret;
1097
1098error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301100 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001101
1102error_config:
1103 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001105
1106 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107}
1108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001109/* must be called with out->lock locked */
1110static int send_offload_cmd_l(struct stream_out* out, int command)
1111{
1112 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1113
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001114 if (!cmd) {
1115 ALOGE("failed to allocate mem for command 0x%x", command);
1116 return -ENOMEM;
1117 }
1118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001119 ALOGVV("%s %d", __func__, command);
1120
1121 cmd->cmd = command;
1122 list_add_tail(&out->offload_cmd_list, &cmd->node);
1123 pthread_cond_signal(&out->offload_cond);
1124 return 0;
1125}
1126
1127/* must be called iwth out->lock locked */
1128static void stop_compressed_output_l(struct stream_out *out)
1129{
1130 out->offload_state = OFFLOAD_STATE_IDLE;
1131 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001132 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001133 if (out->compr != NULL) {
1134 compress_stop(out->compr);
1135 while (out->offload_thread_blocked) {
1136 pthread_cond_wait(&out->cond, &out->lock);
1137 }
1138 }
1139}
1140
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001141bool is_offload_usecase(audio_usecase_t uc_id)
1142{
1143 unsigned int i;
1144 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1145 if (uc_id == offload_usecases[i])
1146 return true;
1147 }
1148 return false;
1149}
1150
1151static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1152{
1153 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1154 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1155 char value[PROPERTY_VALUE_MAX] = {0};
1156
1157 property_get("audio.offload.multiple.enabled", value, NULL);
1158 if (!(atoi(value) || !strncmp("true", value, 4)))
1159 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1160
1161 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1162 for (i = 0; i < num_usecase; i++) {
1163 if (!(adev->offload_usecases_state & (0x1<<i))) {
1164 adev->offload_usecases_state |= 0x1 << i;
1165 ret = offload_usecases[i];
1166 break;
1167 }
1168 }
1169 ALOGV("%s: offload usecase is %d", __func__, ret);
1170 return ret;
1171}
1172
1173static void free_offload_usecase(struct audio_device *adev,
1174 audio_usecase_t uc_id)
1175{
1176 unsigned int i;
1177 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1178 if (offload_usecases[i] == uc_id) {
1179 adev->offload_usecases_state &= ~(0x1<<i);
1180 break;
1181 }
1182 }
1183 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1184}
1185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001186static void *offload_thread_loop(void *context)
1187{
1188 struct stream_out *out = (struct stream_out *) context;
1189 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001190 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001191
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001192 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1193 set_sched_policy(0, SP_FOREGROUND);
1194 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1195
1196 ALOGV("%s", __func__);
1197 pthread_mutex_lock(&out->lock);
1198 for (;;) {
1199 struct offload_cmd *cmd = NULL;
1200 stream_callback_event_t event;
1201 bool send_callback = false;
1202
1203 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1204 __func__, list_empty(&out->offload_cmd_list),
1205 out->offload_state);
1206 if (list_empty(&out->offload_cmd_list)) {
1207 ALOGV("%s SLEEPING", __func__);
1208 pthread_cond_wait(&out->offload_cond, &out->lock);
1209 ALOGV("%s RUNNING", __func__);
1210 continue;
1211 }
1212
1213 item = list_head(&out->offload_cmd_list);
1214 cmd = node_to_item(item, struct offload_cmd, node);
1215 list_remove(item);
1216
1217 ALOGVV("%s STATE %d CMD %d out->compr %p",
1218 __func__, out->offload_state, cmd->cmd, out->compr);
1219
1220 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1221 free(cmd);
1222 break;
1223 }
1224
1225 if (out->compr == NULL) {
1226 ALOGE("%s: Compress handle is NULL", __func__);
1227 pthread_cond_signal(&out->cond);
1228 continue;
1229 }
1230 out->offload_thread_blocked = true;
1231 pthread_mutex_unlock(&out->lock);
1232 send_callback = false;
1233 switch(cmd->cmd) {
1234 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001235 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001236 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001237 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238 send_callback = true;
1239 event = STREAM_CBK_EVENT_WRITE_READY;
1240 break;
1241 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001242 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301243 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001244 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301245 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001246 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301247 if (ret < 0)
1248 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301249 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301250 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001251 compress_drain(out->compr);
1252 else
1253 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301254 if (ret != -ENETRESET) {
1255 send_callback = true;
1256 event = STREAM_CBK_EVENT_DRAIN_READY;
1257 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1258 } else
1259 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260 break;
1261 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001262 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001263 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001264 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001265 send_callback = true;
1266 event = STREAM_CBK_EVENT_DRAIN_READY;
1267 break;
1268 default:
1269 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1270 break;
1271 }
1272 pthread_mutex_lock(&out->lock);
1273 out->offload_thread_blocked = false;
1274 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001275 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001276 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001278 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001279 free(cmd);
1280 }
1281
1282 pthread_cond_signal(&out->cond);
1283 while (!list_empty(&out->offload_cmd_list)) {
1284 item = list_head(&out->offload_cmd_list);
1285 list_remove(item);
1286 free(node_to_item(item, struct offload_cmd, node));
1287 }
1288 pthread_mutex_unlock(&out->lock);
1289
1290 return NULL;
1291}
1292
1293static int create_offload_callback_thread(struct stream_out *out)
1294{
1295 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1296 list_init(&out->offload_cmd_list);
1297 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1298 offload_thread_loop, out);
1299 return 0;
1300}
1301
1302static int destroy_offload_callback_thread(struct stream_out *out)
1303{
1304 pthread_mutex_lock(&out->lock);
1305 stop_compressed_output_l(out);
1306 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1307
1308 pthread_mutex_unlock(&out->lock);
1309 pthread_join(out->offload_thread, (void **) NULL);
1310 pthread_cond_destroy(&out->offload_cond);
1311
1312 return 0;
1313}
1314
Eric Laurent07eeafd2013-10-06 12:52:49 -07001315static bool allow_hdmi_channel_config(struct audio_device *adev)
1316{
1317 struct listnode *node;
1318 struct audio_usecase *usecase;
1319 bool ret = true;
1320
1321 list_for_each(node, &adev->usecase_list) {
1322 usecase = node_to_item(node, struct audio_usecase, list);
1323 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1324 /*
1325 * If voice call is already existing, do not proceed further to avoid
1326 * disabling/enabling both RX and TX devices, CSD calls, etc.
1327 * Once the voice call done, the HDMI channels can be configured to
1328 * max channels of remaining use cases.
1329 */
1330 if (usecase->id == USECASE_VOICE_CALL) {
1331 ALOGD("%s: voice call is active, no change in HDMI channels",
1332 __func__);
1333 ret = false;
1334 break;
1335 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1336 ALOGD("%s: multi channel playback is active, "
1337 "no change in HDMI channels", __func__);
1338 ret = false;
1339 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001340 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001341 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001342 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1343 ", no change in HDMI channels", __func__,
1344 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001345 ret = false;
1346 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347 }
1348 }
1349 }
1350 return ret;
1351}
1352
1353static int check_and_set_hdmi_channels(struct audio_device *adev,
1354 unsigned int channels)
1355{
1356 struct listnode *node;
1357 struct audio_usecase *usecase;
1358
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001359 unsigned int supported_channels = platform_edid_get_max_channels(
1360 adev->platform);
1361 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001362 /* Check if change in HDMI channel config is allowed */
1363 if (!allow_hdmi_channel_config(adev))
1364 return 0;
1365
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001366 if (channels > supported_channels)
1367 channels = supported_channels;
1368
Eric Laurent07eeafd2013-10-06 12:52:49 -07001369 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001370 ALOGD("%s: Requested channels are same as current channels(%d)",
1371 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001372 return 0;
1373 }
1374
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001375 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001376 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001377 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001378 adev->cur_hdmi_channels = channels;
1379
1380 /*
1381 * Deroute all the playback streams routed to HDMI so that
1382 * the back end is deactivated. Note that backend will not
1383 * be deactivated if any one stream is connected to it.
1384 */
1385 list_for_each(node, &adev->usecase_list) {
1386 usecase = node_to_item(node, struct audio_usecase, list);
1387 if (usecase->type == PCM_PLAYBACK &&
1388 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001389 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001390 }
1391 }
1392
1393 /*
1394 * Enable all the streams disabled above. Now the HDMI backend
1395 * will be activated with new channel configuration
1396 */
1397 list_for_each(node, &adev->usecase_list) {
1398 usecase = node_to_item(node, struct audio_usecase, list);
1399 if (usecase->type == PCM_PLAYBACK &&
1400 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001401 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 }
1403 }
1404
1405 return 0;
1406}
1407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408static int stop_output_stream(struct stream_out *out)
1409{
1410 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 struct audio_usecase *uc_info;
1412 struct audio_device *adev = out->dev;
1413
Eric Laurent994a6932013-07-17 11:51:42 -07001414 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 uc_info = get_usecase_from_list(adev, out->usecase);
1417 if (uc_info == NULL) {
1418 ALOGE("%s: Could not find the usecase (%d) in the list",
1419 __func__, out->usecase);
1420 return -EINVAL;
1421 }
1422
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001423 if (is_offload_usecase(out->usecase) &&
1424 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001425 if (adev->visualizer_stop_output != NULL)
1426 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001427
1428 audio_extn_dts_remove_state_notifier_node(out->usecase);
1429
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001430 if (adev->offload_effects_stop_output != NULL)
1431 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1432 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001433
Eric Laurent150dbfe2013-02-27 14:31:02 -08001434 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001435 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001436
1437 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001438 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001440 list_remove(&uc_info->list);
1441 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001443 if (is_offload_usecase(out->usecase) &&
1444 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1445 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1446 ALOGV("Disable passthrough , reset mixer to pcm");
1447 /* NO_PASSTHROUGH */
1448 out->compr_config.codec->compr_passthr = 0;
1449 audio_extn_dolby_set_hdmi_config(adev, out);
1450 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1451 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001452 /* Must be called after removing the usecase from list */
1453 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1454 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1455
Eric Laurent994a6932013-07-17 11:51:42 -07001456 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 return ret;
1458}
1459
1460int start_output_stream(struct stream_out *out)
1461{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001463 int sink_channels = 0;
1464 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 struct audio_usecase *uc_info;
1466 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301467 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001469 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1470 ret = -EINVAL;
1471 goto error_config;
1472 }
1473
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301474 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1475 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1476 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301477
Naresh Tanniru80659832014-06-04 18:17:56 +05301478 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301479 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301480 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301481 goto error_config;
1482 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301483
Eric Laurentb23d5282013-05-14 15:27:20 -07001484 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 if (out->pcm_device_id < 0) {
1486 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1487 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001488 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001489 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 }
1491
1492 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001493
1494 if (!uc_info) {
1495 ret = -ENOMEM;
1496 goto error_config;
1497 }
1498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 uc_info->id = out->usecase;
1500 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001501 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 uc_info->devices = out->devices;
1503 uc_info->in_snd_device = SND_DEVICE_NONE;
1504 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001505 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001506 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001507 if (is_offload_usecase(out->usecase)) {
1508 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001509 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1510 }
1511 }
Mingming Yin9c041392014-05-01 15:37:31 -07001512 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1513 if (!strncmp("true", prop_value, 4)) {
1514 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001515 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1516 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001517 check_and_set_hdmi_channels(adev, sink_channels);
1518 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001519 if (is_offload_usecase(out->usecase)) {
1520 unsigned int ch_count = out->compr_config.codec->ch_in;
1521 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1522 /* backend channel config for passthrough stream is stereo */
1523 ch_count = 2;
1524 check_and_set_hdmi_channels(adev, ch_count);
1525 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001526 check_and_set_hdmi_channels(adev, out->config.channels);
1527 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001528 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001529 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001530 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 select_devices(adev, out->usecase);
1533
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001534 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1535 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001536 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001537 unsigned int flags = PCM_OUT;
1538 unsigned int pcm_open_retry_count = 0;
1539 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1540 flags |= PCM_MMAP | PCM_NOIRQ;
1541 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1542 } else
1543 flags |= PCM_MONOTONIC;
1544
1545 while (1) {
1546 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1547 flags, &out->config);
1548 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1549 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1550 if (out->pcm != NULL) {
1551 pcm_close(out->pcm);
1552 out->pcm = NULL;
1553 }
1554 if (pcm_open_retry_count-- == 0) {
1555 ret = -EIO;
1556 goto error_open;
1557 }
1558 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1559 continue;
1560 }
1561 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001563 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1564 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001565 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001566 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1567 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001569 out->compr = compress_open(adev->snd_card,
1570 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571 COMPRESS_IN, &out->compr_config);
1572 if (out->compr && !is_compress_ready(out->compr)) {
1573 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1574 compress_close(out->compr);
1575 out->compr = NULL;
1576 ret = -EIO;
1577 goto error_open;
1578 }
1579 if (out->offload_callback)
1580 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001581
Fred Oh3f43e742015-03-04 18:42:34 -08001582 /* Since small bufs uses blocking writes, a write will be blocked
1583 for the default max poll time (20s) in the event of an SSR.
1584 Reduce the poll time to observe and deal with SSR faster.
1585 */
1586 if (out->use_small_bufs) {
1587 compress_set_max_poll_wait(out->compr, 1000);
1588 }
1589
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001590 audio_extn_dts_create_state_notifier_node(out->usecase);
1591 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1592 popcount(out->channel_mask),
1593 out->playback_started);
1594
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001595#ifdef DS1_DOLBY_DDP_ENABLED
1596 if (audio_extn_is_dolby_format(out->format))
1597 audio_extn_dolby_send_ddp_endp_params(adev);
1598#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001599 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1600 if (adev->visualizer_start_output != NULL)
1601 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1602 if (adev->offload_effects_start_output != NULL)
1603 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001604 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
Eric Laurent994a6932013-07-17 11:51:42 -07001607 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001611error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001612 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613}
1614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615static int check_input_parameters(uint32_t sample_rate,
1616 audio_format_t format,
1617 int channel_count)
1618{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001619 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001621 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001622 !voice_extn_compress_voip_is_format_supported(format) &&
1623 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001624
1625 switch (channel_count) {
1626 case 1:
1627 case 2:
1628 case 6:
1629 break;
1630 default:
1631 ret = -EINVAL;
1632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633
1634 switch (sample_rate) {
1635 case 8000:
1636 case 11025:
1637 case 12000:
1638 case 16000:
1639 case 22050:
1640 case 24000:
1641 case 32000:
1642 case 44100:
1643 case 48000:
1644 break;
1645 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001646 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 }
1648
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001649 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650}
1651
1652static size_t get_input_buffer_size(uint32_t sample_rate,
1653 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001654 int channel_count,
1655 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656{
1657 size_t size = 0;
1658
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001659 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1660 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001662 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001663 if (is_low_latency)
1664 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001665 /* ToDo: should use frame_size computed based on the format and
1666 channel_count here. */
1667 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001669 /* make sure the size is multiple of 32 bytes
1670 * At 48 kHz mono 16-bit PCM:
1671 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1672 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1673 */
1674 size += 0x1f;
1675 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001676
1677 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
1680static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1681{
1682 struct stream_out *out = (struct stream_out *)stream;
1683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685}
1686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001687static int out_set_sample_rate(struct audio_stream *stream __unused,
1688 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689{
1690 return -ENOSYS;
1691}
1692
1693static size_t out_get_buffer_size(const struct audio_stream *stream)
1694{
1695 struct stream_out *out = (struct stream_out *)stream;
1696
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001697 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001698 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001699 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1700 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001701
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001702 return out->config.period_size *
1703 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704}
1705
1706static uint32_t out_get_channels(const struct audio_stream *stream)
1707{
1708 struct stream_out *out = (struct stream_out *)stream;
1709
1710 return out->channel_mask;
1711}
1712
1713static audio_format_t out_get_format(const struct audio_stream *stream)
1714{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 struct stream_out *out = (struct stream_out *)stream;
1716
1717 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718}
1719
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001720static int out_set_format(struct audio_stream *stream __unused,
1721 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722{
1723 return -ENOSYS;
1724}
1725
1726static int out_standby(struct audio_stream *stream)
1727{
1728 struct stream_out *out = (struct stream_out *)stream;
1729 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301731 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1732 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001733 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1734 /* Ignore standby in case of voip call because the voip output
1735 * stream is closed in adev_close_output_stream()
1736 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301737 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001738 return 0;
1739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001743 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001745 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 if (out->pcm) {
1747 pcm_close(out->pcm);
1748 out->pcm = NULL;
1749 }
1750 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001751 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001753 out->gapless_mdata.encoder_delay = 0;
1754 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 if (out->compr != NULL) {
1756 compress_close(out->compr);
1757 out->compr = NULL;
1758 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001761 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 }
1763 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001764 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 return 0;
1766}
1767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001768static int out_dump(const struct audio_stream *stream __unused,
1769 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770{
1771 return 0;
1772}
1773
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001774static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1775{
1776 int ret = 0;
1777 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001778 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001779
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001780 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001781 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782 return -EINVAL;
1783 }
1784
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001785 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1786 if (ret >= 0) {
1787 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1788 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1789 ALOGV("ADTS format is set in offload mode");
1790 }
1791 out->send_new_metadata = 1;
1792 }
1793
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301794 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001795
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001796 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1797 if(ret >= 0)
1798 is_meta_data_params = true;
1799 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301800 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001801 is_meta_data_params = true;
1802 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301803 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001804 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1806 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001807 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301808 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001810 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1811 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001812 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301813 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 }
1815
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001816 if(!is_meta_data_params) {
1817 ALOGV("%s: Not gapless meta data params", __func__);
1818 return 0;
1819 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820 out->send_new_metadata = 1;
1821 ALOGV("%s new encoder delay %u and padding %u", __func__,
1822 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1823
1824 return 0;
1825}
1826
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001827static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1828{
1829 return out == adev->primary_output || out == adev->voice_tx_output;
1830}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1833{
1834 struct stream_out *out = (struct stream_out *)stream;
1835 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001836 struct audio_usecase *usecase;
1837 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 struct str_parms *parms;
1839 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001840 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001841 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
sangwoobc677242013-08-08 16:53:43 +09001843 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001844 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301846 if (!parms)
1847 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001848 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1849 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001852 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301855 * When HDMI cable is unplugged/usb hs is disconnected the
1856 * music playback is paused and the policy manager sends routing=0
1857 * But the audioflingercontinues to write data until standby time
1858 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001859 * Avoid this by routing audio to speaker until standby.
1860 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301861 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1862 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001863 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001864 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1865 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001866 }
1867
1868 /*
1869 * select_devices() call below switches all the usecases on the same
1870 * backend to the new device. Refer to check_usecases_codec_backend() in
1871 * the select_devices(). But how do we undo this?
1872 *
1873 * For example, music playback is active on headset (deep-buffer usecase)
1874 * and if we go to ringtones and select a ringtone, low-latency usecase
1875 * will be started on headset+speaker. As we can't enable headset+speaker
1876 * and headset devices at the same time, select_devices() switches the music
1877 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1878 * So when the ringtone playback is completed, how do we undo the same?
1879 *
1880 * We are relying on the out_set_parameters() call on deep-buffer output,
1881 * once the ringtone playback is ended.
1882 * NOTE: We should not check if the current devices are same as new devices.
1883 * Because select_devices() must be called to switch back the music
1884 * playback to headset.
1885 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001886 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 out->devices = val;
1888
1889 if (!out->standby)
1890 select_devices(adev, out->usecase);
1891
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001892 if (output_drives_call(adev, out)) {
1893 if(!voice_is_in_call(adev)) {
1894 if (adev->mode == AUDIO_MODE_IN_CALL) {
1895 adev->current_call_output = out;
1896 ret = voice_start_call(adev);
1897 }
1898 } else {
1899 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001900 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001901 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001902 }
1903 }
1904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001906 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001908
1909 if (out == adev->primary_output) {
1910 pthread_mutex_lock(&adev->lock);
1911 audio_extn_set_parameters(adev, parms);
1912 pthread_mutex_unlock(&adev->lock);
1913 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001914 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001915 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001916 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001917
1918 audio_extn_dts_create_state_notifier_node(out->usecase);
1919 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1920 popcount(out->channel_mask),
1921 out->playback_started);
1922
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001923 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001924 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301927error:
Eric Laurent994a6932013-07-17 11:51:42 -07001928 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 return ret;
1930}
1931
1932static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1933{
1934 struct stream_out *out = (struct stream_out *)stream;
1935 struct str_parms *query = str_parms_create_str(keys);
1936 char *str;
1937 char value[256];
1938 struct str_parms *reply = str_parms_create();
1939 size_t i, j;
1940 int ret;
1941 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001942
1943 if (!query || !reply) {
1944 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1945 return NULL;
1946 }
1947
Eric Laurent994a6932013-07-17 11:51:42 -07001948 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1950 if (ret >= 0) {
1951 value[0] = '\0';
1952 i = 0;
1953 while (out->supported_channel_masks[i] != 0) {
1954 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1955 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1956 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001957 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001959 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 first = false;
1961 break;
1962 }
1963 }
1964 i++;
1965 }
1966 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1967 str = str_parms_to_str(reply);
1968 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001969 voice_extn_out_get_parameters(out, query, reply);
1970 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001971 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001972 free(str);
1973 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001976
1977 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1978 if (ret >= 0) {
1979 value[0] = '\0';
1980 i = 0;
1981 first = true;
1982 while (out->supported_formats[i] != 0) {
1983 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1984 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1985 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001986 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001987 }
1988 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1989 first = false;
1990 break;
1991 }
1992 }
1993 i++;
1994 }
1995 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
1996 str = str_parms_to_str(reply);
1997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 str_parms_destroy(query);
1999 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002000 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 return str;
2002}
2003
2004static uint32_t out_get_latency(const struct audio_stream_out *stream)
2005{
2006 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002007 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008
Alexy Josephaa54c872014-12-03 02:46:47 -08002009 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002010 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002011 } else {
2012 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002014 }
2015
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302016 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002017 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018}
2019
2020static int out_set_volume(struct audio_stream_out *stream, float left,
2021 float right)
2022{
Eric Laurenta9024de2013-04-04 09:19:12 -07002023 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 int volume[2];
2025
Eric Laurenta9024de2013-04-04 09:19:12 -07002026 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2027 /* only take left channel into account: the API is for stereo anyway */
2028 out->muted = (left == 0.0f);
2029 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002030 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002031 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2032 /*
2033 * Set mute or umute on HDMI passthrough stream.
2034 * Only take left channel into account.
2035 * Mute is 0 and unmute 1
2036 */
2037 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2038 } else {
2039 char mixer_ctl_name[128];
2040 struct audio_device *adev = out->dev;
2041 struct mixer_ctl *ctl;
2042 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002043 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002045 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2046 "Compress Playback %d Volume", pcm_device_id);
2047 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2048 if (!ctl) {
2049 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2050 __func__, mixer_ctl_name);
2051 return -EINVAL;
2052 }
2053 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2054 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2055 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2056 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 return -ENOSYS;
2061}
2062
2063static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2064 size_t bytes)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
2067 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302068 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002069 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302072
Naresh Tanniru80659832014-06-04 18:17:56 +05302073 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002074 // increase written size during SSR to avoid mismatch
2075 // with the written frames count in AF
2076 if (!is_offload_usecase(out->usecase))
2077 out->written += bytes / (out->config.channels * sizeof(short));
2078
Naresh Tanniru80659832014-06-04 18:17:56 +05302079 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302080 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302081 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302082 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002083 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302084 //during SSR for compress usecase we should return error to flinger
2085 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2086 pthread_mutex_unlock(&out->lock);
2087 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302088 }
2089 }
2090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002092 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002093 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002094 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2095 ret = voice_extn_compress_voip_start_output_stream(out);
2096 else
2097 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002098 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002101 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 goto exit;
2103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002106 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002107 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002108 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002109 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002110 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2111 out->send_new_metadata = 0;
2112 }
2113
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302115 if (ret < 0)
2116 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002117 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002118 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302119 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302121 } else if (-ENETRESET == ret) {
2122 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2123 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2124 pthread_mutex_unlock(&out->lock);
2125 out_standby(&out->stream.common);
2126 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002130 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 out->playback_started = 1;
2132 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002133
2134 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2135 popcount(out->channel_mask),
2136 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 }
2138 pthread_mutex_unlock(&out->lock);
2139 return ret;
2140 } else {
2141 if (out->pcm) {
2142 if (out->muted)
2143 memset((void *)buffer, 0, bytes);
2144 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002145 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2146 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2147 else
2148 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302149 if (ret < 0)
2150 ret = -errno;
2151 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002152 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 }
2155
2156exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302157 /* ToDo: There may be a corner case when SSR happens back to back during
2158 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302159 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302160 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161 }
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 pthread_mutex_unlock(&out->lock);
2164
2165 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002166 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002167 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302168 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302169 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302170 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302171 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302172 out->standby = true;
2173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002175 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302176 out_get_sample_rate(&out->stream.common));
2177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 }
2179 return bytes;
2180}
2181
2182static int out_get_render_position(const struct audio_stream_out *stream,
2183 uint32_t *dsp_frames)
2184{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302186 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002187
2188 if (dsp_frames == NULL)
2189 return -EINVAL;
2190
2191 *dsp_frames = 0;
2192 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002193 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 pthread_mutex_lock(&out->lock);
2195 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302196 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302198 if (ret < 0)
2199 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 ALOGVV("%s rendered frames %d sample_rate %d",
2201 __func__, *dsp_frames, out->sample_rate);
2202 }
2203 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 if (-ENETRESET == ret) {
2205 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2206 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2207 return -EINVAL;
2208 } else if(ret < 0) {
2209 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2210 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302211 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2212 /*
2213 * Handle corner case where compress session is closed during SSR
2214 * and timestamp is queried
2215 */
2216 ALOGE(" ERROR: sound card not active, return error");
2217 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302218 } else {
2219 return 0;
2220 }
Zhou Song32a556e2015-05-05 10:46:56 +08002221 } else if (audio_is_linear_pcm(out->format)) {
2222 *dsp_frames = out->written;
2223 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 } else
2225 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226}
2227
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002228static int out_add_audio_effect(const struct audio_stream *stream __unused,
2229 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230{
2231 return 0;
2232}
2233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002234static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2235 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236{
2237 return 0;
2238}
2239
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002240static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2241 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242{
2243 return -EINVAL;
2244}
2245
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002246static int out_get_presentation_position(const struct audio_stream_out *stream,
2247 uint64_t *frames, struct timespec *timestamp)
2248{
2249 struct stream_out *out = (struct stream_out *)stream;
2250 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002251 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002252
2253 pthread_mutex_lock(&out->lock);
2254
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002255 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002256 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302257 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002258 &out->sample_rate);
2259 ALOGVV("%s rendered frames %ld sample_rate %d",
2260 __func__, dsp_frames, out->sample_rate);
2261 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302262 if (ret < 0)
2263 ret = -errno;
2264 if (-ENETRESET == ret) {
2265 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2266 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2267 ret = -EINVAL;
2268 } else
2269 ret = 0;
2270
Eric Laurent949a0892013-09-20 09:20:13 -07002271 /* this is the best we can do */
2272 clock_gettime(CLOCK_MONOTONIC, timestamp);
2273 }
2274 } else {
2275 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002276 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002277 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2278 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002279 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002280 // This adjustment accounts for buffering after app processor.
2281 // It is based on estimated DSP latency per use case, rather than exact.
2282 signed_frames -=
2283 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2284
Eric Laurent949a0892013-09-20 09:20:13 -07002285 // It would be unusual for this value to be negative, but check just in case ...
2286 if (signed_frames >= 0) {
2287 *frames = signed_frames;
2288 ret = 0;
2289 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002290 }
2291 }
2292 }
2293
2294 pthread_mutex_unlock(&out->lock);
2295
2296 return ret;
2297}
2298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299static int out_set_callback(struct audio_stream_out *stream,
2300 stream_callback_t callback, void *cookie)
2301{
2302 struct stream_out *out = (struct stream_out *)stream;
2303
2304 ALOGV("%s", __func__);
2305 pthread_mutex_lock(&out->lock);
2306 out->offload_callback = callback;
2307 out->offload_cookie = cookie;
2308 pthread_mutex_unlock(&out->lock);
2309 return 0;
2310}
2311
2312static int out_pause(struct audio_stream_out* stream)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315 int status = -ENOSYS;
2316 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002317 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002318 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002319 pthread_mutex_lock(&out->lock);
2320 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302321 struct audio_device *adev = out->dev;
2322 int snd_scard_state = get_snd_card_state(adev);
2323
2324 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2325 status = compress_pause(out->compr);
2326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002328
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302329 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002330 audio_extn_dts_notify_playback_state(out->usecase, 0,
2331 out->sample_rate, popcount(out->channel_mask),
2332 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333 }
2334 pthread_mutex_unlock(&out->lock);
2335 }
2336 return status;
2337}
2338
2339static int out_resume(struct audio_stream_out* stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342 int status = -ENOSYS;
2343 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002344 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002345 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 status = 0;
2347 pthread_mutex_lock(&out->lock);
2348 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302349 struct audio_device *adev = out->dev;
2350 int snd_scard_state = get_snd_card_state(adev);
2351
2352 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2353 status = compress_resume(out->compr);
2354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002356
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302357 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002358 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2359 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 }
2361 pthread_mutex_unlock(&out->lock);
2362 }
2363 return status;
2364}
2365
2366static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2367{
2368 struct stream_out *out = (struct stream_out *)stream;
2369 int status = -ENOSYS;
2370 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002371 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 pthread_mutex_lock(&out->lock);
2373 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2374 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2375 else
2376 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2377 pthread_mutex_unlock(&out->lock);
2378 }
2379 return status;
2380}
2381
2382static int out_flush(struct audio_stream_out* stream)
2383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002386 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002387 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 pthread_mutex_lock(&out->lock);
2389 stop_compressed_output_l(out);
2390 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002391 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 return 0;
2393 }
2394 return -ENOSYS;
2395}
2396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397/** audio_stream_in implementation **/
2398static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2399{
2400 struct stream_in *in = (struct stream_in *)stream;
2401
2402 return in->config.rate;
2403}
2404
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002405static int in_set_sample_rate(struct audio_stream *stream __unused,
2406 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407{
2408 return -ENOSYS;
2409}
2410
2411static size_t in_get_buffer_size(const struct audio_stream *stream)
2412{
2413 struct stream_in *in = (struct stream_in *)stream;
2414
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002415 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2416 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002417 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2418 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002419
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002420 return in->config.period_size *
2421 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422}
2423
2424static uint32_t in_get_channels(const struct audio_stream *stream)
2425{
2426 struct stream_in *in = (struct stream_in *)stream;
2427
2428 return in->channel_mask;
2429}
2430
2431static audio_format_t in_get_format(const struct audio_stream *stream)
2432{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002433 struct stream_in *in = (struct stream_in *)stream;
2434
2435 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436}
2437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002438static int in_set_format(struct audio_stream *stream __unused,
2439 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440{
2441 return -ENOSYS;
2442}
2443
2444static int in_standby(struct audio_stream *stream)
2445{
2446 struct stream_in *in = (struct stream_in *)stream;
2447 struct audio_device *adev = in->dev;
2448 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302449 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2450 stream, in->usecase, use_case_table[in->usecase]);
2451
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002452 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2453 /* Ignore standby in case of voip call because the voip input
2454 * stream is closed in adev_close_input_stream()
2455 */
2456 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2457 return status;
2458 }
2459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002461 if (!in->standby && in->is_st_session) {
2462 ALOGD("%s: sound trigger pcm stop lab", __func__);
2463 audio_extn_sound_trigger_stop_lab(in);
2464 in->standby = 1;
2465 }
2466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002468 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002470 if (in->pcm) {
2471 pcm_close(in->pcm);
2472 in->pcm = NULL;
2473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002475 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 }
2477 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002478 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 return status;
2480}
2481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002482static int in_dump(const struct audio_stream *stream __unused,
2483 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return 0;
2486}
2487
2488static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491 struct audio_device *adev = in->dev;
2492 struct str_parms *parms;
2493 char *str;
2494 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002495 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302497 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 parms = str_parms_create_str(kvpairs);
2499
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302500 if (!parms)
2501 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002503 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002504
2505 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2506 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 val = atoi(value);
2508 /* no audio source uses val == 0 */
2509 if ((in->source != val) && (val != 0)) {
2510 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002511 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2512 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2513 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2514 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002515 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002516 err = voice_extn_compress_voip_open_input_stream(in);
2517 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002518 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002519 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002520 }
2521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 }
2523 }
2524
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002525 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2526 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002528 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 in->device = val;
2530 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002531 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002532 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 }
2534 }
2535
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002536done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002538 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539
2540 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302541error:
Eric Laurent994a6932013-07-17 11:51:42 -07002542 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 return ret;
2544}
2545
2546static char* in_get_parameters(const struct audio_stream *stream,
2547 const char *keys)
2548{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002549 struct stream_in *in = (struct stream_in *)stream;
2550 struct str_parms *query = str_parms_create_str(keys);
2551 char *str;
2552 char value[256];
2553 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002554
2555 if (!query || !reply) {
2556 ALOGE("in_get_parameters: failed to create query or reply");
2557 return NULL;
2558 }
2559
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002560 ALOGV("%s: enter: keys - %s", __func__, keys);
2561
2562 voice_extn_in_get_parameters(in, query, reply);
2563
2564 str = str_parms_to_str(reply);
2565 str_parms_destroy(query);
2566 str_parms_destroy(reply);
2567
2568 ALOGV("%s: exit: returns - %s", __func__, str);
2569 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570}
2571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002572static int in_set_gain(struct audio_stream_in *stream __unused,
2573 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574{
2575 return 0;
2576}
2577
2578static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2579 size_t bytes)
2580{
2581 struct stream_in *in = (struct stream_in *)stream;
2582 struct audio_device *adev = in->dev;
2583 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302584 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302587
2588 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302589 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302590 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302591 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302592 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002593 } else {
2594 if (in->is_st_session && !in->is_st_session_active) {
2595 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2596 ret= -EIO;;
2597 goto exit;
2598 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302599 }
2600 }
2601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002603 if (!in->is_st_session) {
2604 pthread_mutex_lock(&adev->lock);
2605 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2606 ret = voice_extn_compress_voip_start_input_stream(in);
2607 else
2608 ret = start_input_stream(in);
2609 pthread_mutex_unlock(&adev->lock);
2610 if (ret != 0) {
2611 goto exit;
2612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 }
2614 in->standby = 0;
2615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616
2617 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002618 if (audio_extn_ssr_get_enabled() &&
2619 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002620 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002621 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2622 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002623 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2624 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002625 else
2626 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302627 if (ret < 0)
2628 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 }
2630
2631 /*
2632 * Instead of writing zeroes here, we could trust the hardware
2633 * to always provide zeroes when muted.
2634 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302635 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2636 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 memset(buffer, 0, bytes);
2638
2639exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302640 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302641 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302642 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002643 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2644 session reading on LAB data. In this case do not set sound card state
2645 offline, instead mark this sound trigger session inactive to avoid
2646 further reading of LAB data from CPE driver. Marking the session
2647 inactive handles both CPE and ADSP SSR for sound trigger session */
2648 if (!in->is_st_session)
2649 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2650 else
2651 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 pthread_mutex_unlock(&in->lock);
2654
2655 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302656 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302657 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302658 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302659 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302660 in->standby = true;
2661 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302662 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002664 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002665 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302666 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668 return bytes;
2669}
2670
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002671static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672{
2673 return 0;
2674}
2675
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002676static int add_remove_audio_effect(const struct audio_stream *stream,
2677 effect_handle_t effect,
2678 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002680 struct stream_in *in = (struct stream_in *)stream;
2681 int status = 0;
2682 effect_descriptor_t desc;
2683
2684 status = (*effect)->get_descriptor(effect, &desc);
2685 if (status != 0)
2686 return status;
2687
2688 pthread_mutex_lock(&in->lock);
2689 pthread_mutex_lock(&in->dev->lock);
2690 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2691 in->enable_aec != enable &&
2692 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2693 in->enable_aec = enable;
2694 if (!in->standby)
2695 select_devices(in->dev, in->usecase);
2696 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002697 if (in->enable_ns != enable &&
2698 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2699 in->enable_ns = enable;
2700 if (!in->standby)
2701 select_devices(in->dev, in->usecase);
2702 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002703 pthread_mutex_unlock(&in->dev->lock);
2704 pthread_mutex_unlock(&in->lock);
2705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 return 0;
2707}
2708
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002709static int in_add_audio_effect(const struct audio_stream *stream,
2710 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711{
Eric Laurent994a6932013-07-17 11:51:42 -07002712 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713 return add_remove_audio_effect(stream, effect, true);
2714}
2715
2716static int in_remove_audio_effect(const struct audio_stream *stream,
2717 effect_handle_t effect)
2718{
Eric Laurent994a6932013-07-17 11:51:42 -07002719 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002720 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721}
2722
2723static int adev_open_output_stream(struct audio_hw_device *dev,
2724 audio_io_handle_t handle,
2725 audio_devices_t devices,
2726 audio_output_flags_t flags,
2727 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002728 struct audio_stream_out **stream_out,
2729 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730{
2731 struct audio_device *adev = (struct audio_device *)dev;
2732 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002733 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002734 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302737
2738 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2739 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2740 ALOGE(" sound card is not active rejecting compress output open request");
2741 return -EINVAL;
2742 }
2743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2745
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302746 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2747 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2748 devices, flags, &out->stream);
2749
2750
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002751 if (!out) {
2752 return -ENOMEM;
2753 }
2754
Haynes Mathew George204045b2015-02-25 20:32:03 -08002755 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2756 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 if (devices == AUDIO_DEVICE_NONE)
2759 devices = AUDIO_DEVICE_OUT_SPEAKER;
2760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 out->flags = flags;
2762 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002763 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002764 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 out->sample_rate = config->sample_rate;
2766 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2767 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002768 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002769 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002770 out->non_blocking = 0;
2771 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772
2773 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002774 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2775 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2776 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2777
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002778 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002779 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2780 ret = read_hdmi_channel_masks(out);
2781
2782 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2783 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002784 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002785 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002786 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002787
2788 if (config->sample_rate == 0)
2789 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2790 if (config->channel_mask == 0)
2791 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2792
2793 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2796 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002798 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002800 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2801 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002802 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002803 ret = voice_extn_compress_voip_open_output_stream(out);
2804 if (ret != 0) {
2805 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2806 __func__, ret);
2807 goto error_open;
2808 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2810 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2811 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2812 ALOGE("%s: Unsupported Offload information", __func__);
2813 ret = -EINVAL;
2814 goto error_open;
2815 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002816
2817 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2818 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2819 ALOGV("read and update_pass through formats");
2820 ret = audio_extn_dolby_update_passt_formats(adev, out);
2821 if(ret != 0) {
2822 goto error_open;
2823 }
2824 if(config->offload_info.format == 0)
2825 config->offload_info.format = out->supported_formats[0];
2826 }
2827
Mingming Yin90310102013-11-13 16:57:00 -08002828 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002829 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 ALOGE("%s: Unsupported audio format", __func__);
2831 ret = -EINVAL;
2832 goto error_open;
2833 }
2834
2835 out->compr_config.codec = (struct snd_codec *)
2836 calloc(1, sizeof(struct snd_codec));
2837
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002838 if (!out->compr_config.codec) {
2839 ret = -ENOMEM;
2840 goto error_open;
2841 }
2842
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002843 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 if (config->offload_info.channel_mask)
2845 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002846 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002848 config->offload_info.channel_mask = config->channel_mask;
2849 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002850 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 out->sample_rate = config->offload_info.sample_rate;
2852
2853 out->stream.set_callback = out_set_callback;
2854 out->stream.pause = out_pause;
2855 out->stream.resume = out_resume;
2856 out->stream.drain = out_drain;
2857 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002858 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002860 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002861 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002862 audio_extn_dolby_get_snd_codec_id(adev, out,
2863 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002864 else
2865 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002867 if (audio_is_offload_pcm(config->offload_info.format)) {
2868 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002869 platform_get_pcm_offload_buffer_size(&config->offload_info);
2870 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2871 out->compr_config.fragment_size =
2872 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002873 } else {
2874 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002875 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002876 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2878 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302879 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 out->compr_config.codec->bit_rate =
2881 config->offload_info.bit_rate;
2882 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002883 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002885 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002886 /*TODO: Do we need to change it for passthrough */
2887 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888
Mingming Yin3ee55c62014-08-04 14:23:35 -07002889 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2890 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002891 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2892 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002893 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002894 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2895
Mingming Yin3ee55c62014-08-04 14:23:35 -07002896 if (out->bit_width == 24) {
2897 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2898 }
2899
Amit Shekhar6f461b12014-08-01 14:52:58 -07002900 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002901 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2904 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002905
Alexy Josephaa54c872014-12-03 02:46:47 -08002906 if (config->offload_info.use_small_bufs) {
2907 //this flag is set from framework only if its for PCM formats
2908 //no need to check for PCM format again
2909 out->non_blocking = 0;
2910 out->use_small_bufs = true;
2911 ALOGI("Keep write blocking for small buff: non_blockling %d",
2912 out->non_blocking);
2913 }
2914
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002915 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002916 out->offload_state = OFFLOAD_STATE_IDLE;
2917 out->playback_started = 0;
2918
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002919 audio_extn_dts_create_state_notifier_node(out->usecase);
2920
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 create_offload_callback_thread(out);
2922 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2923 __func__, config->offload_info.version,
2924 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002925 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002926 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002927 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2928 ret = voice_check_and_set_incall_music_usecase(adev, out);
2929 if (ret != 0) {
2930 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2931 __func__, ret);
2932 goto error_open;
2933 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002934 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2935 if (config->sample_rate == 0)
2936 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2937 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2938 config->sample_rate != 8000) {
2939 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2940 ret = -EINVAL;
2941 goto error_open;
2942 }
2943 out->sample_rate = config->sample_rate;
2944 out->config.rate = config->sample_rate;
2945 if (config->format == AUDIO_FORMAT_DEFAULT)
2946 config->format = AUDIO_FORMAT_PCM_16_BIT;
2947 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2948 config->format = AUDIO_FORMAT_PCM_16_BIT;
2949 ret = -EINVAL;
2950 goto error_open;
2951 }
2952 out->format = config->format;
2953 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2954 out->config = pcm_config_afe_proxy_playback;
2955 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002956 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002957 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2959 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002960 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002961 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2962 format = AUDIO_FORMAT_PCM_16_BIT;
2963 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2964 out->config = pcm_config_deep_buffer;
2965 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002966 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002967 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002968 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002969 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002970 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002971 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 }
2973
Amit Shekhar1d896042014-10-03 13:16:09 -07002974 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2975 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002976 /* TODO remove this hardcoding and check why width is zero*/
2977 if (out->bit_width == 0)
2978 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002979 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2980 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002981 devices, flags, format, out->sample_rate,
Manish Dewanganf48adb42015-05-27 10:17:41 +05302982 out->bit_width, out->channel_mask,
2983 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002984 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2985 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2986 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002987 if(adev->primary_output == NULL)
2988 adev->primary_output = out;
2989 else {
2990 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002991 ret = -EEXIST;
2992 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002993 }
2994 }
2995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 /* Check if this usecase is already existing */
2997 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002998 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2999 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003002 ret = -EEXIST;
3003 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 }
3005 pthread_mutex_unlock(&adev->lock);
3006
3007 out->stream.common.get_sample_rate = out_get_sample_rate;
3008 out->stream.common.set_sample_rate = out_set_sample_rate;
3009 out->stream.common.get_buffer_size = out_get_buffer_size;
3010 out->stream.common.get_channels = out_get_channels;
3011 out->stream.common.get_format = out_get_format;
3012 out->stream.common.set_format = out_set_format;
3013 out->stream.common.standby = out_standby;
3014 out->stream.common.dump = out_dump;
3015 out->stream.common.set_parameters = out_set_parameters;
3016 out->stream.common.get_parameters = out_get_parameters;
3017 out->stream.common.add_audio_effect = out_add_audio_effect;
3018 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3019 out->stream.get_latency = out_get_latency;
3020 out->stream.set_volume = out_set_volume;
3021 out->stream.write = out_write;
3022 out->stream.get_render_position = out_get_render_position;
3023 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003024 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003027 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003028 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029
3030 config->format = out->stream.common.get_format(&out->stream.common);
3031 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3032 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3033
3034 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303035 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3036 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003037
3038 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3039 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3040 popcount(out->channel_mask), out->playback_started);
3041
Eric Laurent994a6932013-07-17 11:51:42 -07003042 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003044
3045error_open:
3046 free(out);
3047 *stream_out = NULL;
3048 ALOGD("%s: exit: ret %d", __func__, ret);
3049 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050}
3051
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003052static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 struct audio_stream_out *stream)
3054{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 struct stream_out *out = (struct stream_out *)stream;
3056 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303059 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3060
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303062 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303064 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003065 if(ret != 0)
3066 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3067 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003068 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 out_standby(&stream->common);
3070
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003071 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003072 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003074 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003075 if (out->compr_config.codec != NULL)
3076 free(out->compr_config.codec);
3077 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003078
3079 if (adev->voice_tx_output == out)
3080 adev->voice_tx_output = NULL;
3081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003082 pthread_cond_destroy(&out->cond);
3083 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003085 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086}
3087
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003088static void close_compress_sessions(struct audio_device *adev)
3089{
Mingming Yin7b762e72015-03-04 13:47:32 -08003090 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303091 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003092 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003093 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303094
3095 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003096 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303097 if (is_offload_usecase(usecase->id)) {
3098 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003099 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3100 out = usecase->stream.out;
3101 pthread_mutex_unlock(&adev->lock);
3102 out_standby(&out->stream.common);
3103 pthread_mutex_lock(&adev->lock);
3104 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303105 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003106 }
3107 pthread_mutex_unlock(&adev->lock);
3108}
3109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3111{
3112 struct audio_device *adev = (struct audio_device *)dev;
3113 struct str_parms *parms;
3114 char *str;
3115 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003116 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003117 int ret;
3118 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003120 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303123 if (!parms)
3124 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003125 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3126 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303127 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303128 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303129 struct listnode *node;
3130 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303131 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303132 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003133 //close compress sessions on OFFLINE status
3134 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303135 } else if (strstr(snd_card_status, "ONLINE")) {
3136 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303137 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303138 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303139 }
3140
3141 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003142 status = voice_set_parameters(adev, parms);
3143 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003144 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003146 status = platform_set_parameters(adev->platform, parms);
3147 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003148 goto done;
3149
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003150 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3151 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003152 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3154 adev->bluetooth_nrec = true;
3155 else
3156 adev->bluetooth_nrec = false;
3157 }
3158
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3160 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3162 adev->screen_off = false;
3163 else
3164 adev->screen_off = true;
3165 }
3166
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003167 ret = str_parms_get_int(parms, "rotation", &val);
3168 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003169 bool reverse_speakers = false;
3170 switch(val) {
3171 // FIXME: note that the code below assumes that the speakers are in the correct placement
3172 // relative to the user when the device is rotated 90deg from its default rotation. This
3173 // assumption is device-specific, not platform-specific like this code.
3174 case 270:
3175 reverse_speakers = true;
3176 break;
3177 case 0:
3178 case 90:
3179 case 180:
3180 break;
3181 default:
3182 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003183 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003184 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003185 if (status == 0) {
3186 if (adev->speaker_lr_swap != reverse_speakers) {
3187 adev->speaker_lr_swap = reverse_speakers;
3188 // only update the selected device if there is active pcm playback
3189 struct audio_usecase *usecase;
3190 struct listnode *node;
3191 list_for_each(node, &adev->usecase_list) {
3192 usecase = node_to_item(node, struct audio_usecase, list);
3193 if (usecase->type == PCM_PLAYBACK) {
3194 select_devices(adev, usecase->id);
3195 break;
3196 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
3198 }
3199 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003200 }
3201
Mingming Yin514a8bc2014-07-29 15:22:21 -07003202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3203 if (ret >= 0) {
3204 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3205 adev->bt_wb_speech_enabled = true;
3206 else
3207 adev->bt_wb_speech_enabled = false;
3208 }
3209
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003210 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3211 if (ret >= 0) {
3212 val = atoi(value);
3213 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3214 ALOGV("cache new edid");
3215 platform_cache_edid(adev->platform);
3216 }
3217 }
3218
3219 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3220 if (ret >= 0) {
3221 val = atoi(value);
3222 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3223 ALOGV("invalidate cached edid");
3224 platform_invalidate_edid(adev->platform);
3225 }
3226 }
3227
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003228 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003229
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003230done:
3231 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003232 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303233error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003234 ALOGV("%s: exit with code(%d)", __func__, status);
3235 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236}
3237
3238static char* adev_get_parameters(const struct audio_hw_device *dev,
3239 const char *keys)
3240{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003241 struct audio_device *adev = (struct audio_device *)dev;
3242 struct str_parms *reply = str_parms_create();
3243 struct str_parms *query = str_parms_create_str(keys);
3244 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303245 char value[256] = {0};
3246 int ret = 0;
3247
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003248 if (!query || !reply) {
3249 ALOGE("adev_get_parameters: failed to create query or reply");
3250 return NULL;
3251 }
3252
Naresh Tannirud7205b62014-06-20 02:54:48 +05303253 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3254 sizeof(value));
3255 if (ret >=0) {
3256 int val = 1;
3257 pthread_mutex_lock(&adev->snd_card_status.lock);
3258 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3259 val = 0;
3260 pthread_mutex_unlock(&adev->snd_card_status.lock);
3261 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3262 goto exit;
3263 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003264
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003265 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003266 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003267 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003268 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303269 pthread_mutex_unlock(&adev->lock);
3270
Naresh Tannirud7205b62014-06-20 02:54:48 +05303271exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003272 str = str_parms_to_str(reply);
3273 str_parms_destroy(query);
3274 str_parms_destroy(reply);
3275
3276 ALOGV("%s: exit: returns - %s", __func__, str);
3277 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278}
3279
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003280static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281{
3282 return 0;
3283}
3284
3285static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3286{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003287 int ret;
3288 struct audio_device *adev = (struct audio_device *)dev;
3289 pthread_mutex_lock(&adev->lock);
3290 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003291 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003292 pthread_mutex_unlock(&adev->lock);
3293 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294}
3295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003296static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3297 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298{
3299 return -ENOSYS;
3300}
3301
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003302static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3303 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304{
3305 return -ENOSYS;
3306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3309 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -ENOSYS;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3315 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
3320static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3321{
3322 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 pthread_mutex_lock(&adev->lock);
3325 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003326 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003328 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3329 voice_is_in_call(adev)) {
3330 voice_stop_call(adev);
3331 adev->current_call_output = NULL;
3332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 }
3334 pthread_mutex_unlock(&adev->lock);
3335 return 0;
3336}
3337
3338static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3339{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003340 int ret;
3341
3342 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003343 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003344 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3345 pthread_mutex_unlock(&adev->lock);
3346
3347 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348}
3349
3350static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3351{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003352 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 return 0;
3354}
3355
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003356static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 const struct audio_config *config)
3358{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003359 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003361 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3362 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363}
3364
3365static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003366 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 audio_devices_t devices,
3368 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003369 struct audio_stream_in **stream_in,
3370 audio_input_flags_t flags __unused,
3371 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003372 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373{
3374 struct audio_device *adev = (struct audio_device *)dev;
3375 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003376 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003377 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003378 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 *stream_in = NULL;
3381 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3382 return -EINVAL;
3383
3384 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003385
3386 if (!in) {
3387 ALOGE("failed to allocate input stream");
3388 return -ENOMEM;
3389 }
3390
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303391 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003392 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3393 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003395 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 in->stream.common.get_sample_rate = in_get_sample_rate;
3398 in->stream.common.set_sample_rate = in_set_sample_rate;
3399 in->stream.common.get_buffer_size = in_get_buffer_size;
3400 in->stream.common.get_channels = in_get_channels;
3401 in->stream.common.get_format = in_get_format;
3402 in->stream.common.set_format = in_set_format;
3403 in->stream.common.standby = in_standby;
3404 in->stream.common.dump = in_dump;
3405 in->stream.common.set_parameters = in_set_parameters;
3406 in->stream.common.get_parameters = in_get_parameters;
3407 in->stream.common.add_audio_effect = in_add_audio_effect;
3408 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3409 in->stream.set_gain = in_set_gain;
3410 in->stream.read = in_read;
3411 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3412
3413 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003414 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 in->standby = 1;
3417 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003418 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
3420 /* Update config params with the requested sample rate and channels */
3421 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003422 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3423 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3424 is_low_latency = true;
3425#if LOW_LATENCY_CAPTURE_USE_CASE
3426 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3427#endif
3428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003431 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003433 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303434 if (adev->mode != AUDIO_MODE_IN_CALL) {
3435 ret = -EINVAL;
3436 goto err_open;
3437 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003438 if (config->sample_rate == 0)
3439 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3440 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3441 config->sample_rate != 8000) {
3442 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3443 ret = -EINVAL;
3444 goto err_open;
3445 }
3446 if (config->format == AUDIO_FORMAT_DEFAULT)
3447 config->format = AUDIO_FORMAT_PCM_16_BIT;
3448 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3449 config->format = AUDIO_FORMAT_PCM_16_BIT;
3450 ret = -EINVAL;
3451 goto err_open;
3452 }
3453
3454 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3455 in->config = pcm_config_afe_proxy_record;
3456 in->config.channels = channel_count;
3457 in->config.rate = config->sample_rate;
3458 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003459 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003460 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003461 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003466 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003467 }
Mingming Yine62d7842013-10-25 16:26:03 -07003468 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003469 audio_extn_compr_cap_format_supported(config->format) &&
3470 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003471 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003472 } else {
3473 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003474 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003475 buffer_size = get_input_buffer_size(config->sample_rate,
3476 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003477 channel_count,
3478 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003479 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003480 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3481 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3482 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3483 (in->config.rate == 8000 || in->config.rate == 16000) &&
3484 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3485 voice_extn_compress_voip_open_input_stream(in);
3486 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003489 /* This stream could be for sound trigger lab,
3490 get sound trigger pcm if present */
3491 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303492 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003495 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003496 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
3498err_open:
3499 free(in);
3500 *stream_in = NULL;
3501 return ret;
3502}
3503
3504static void adev_close_input_stream(struct audio_hw_device *dev,
3505 struct audio_stream_in *stream)
3506{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003507 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003509 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303510
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303511 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003512
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303513 /* Disable echo reference while closing input stream */
3514 platform_set_echo_reference(adev->platform, false);
3515
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003516 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303517 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003518 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303519 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003520 if (ret != 0)
3521 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3522 __func__, ret);
3523 } else
3524 in_standby(&stream->common);
3525
Mingming Yin7b762e72015-03-04 13:47:32 -08003526 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003527 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003528 audio_extn_ssr_deinit();
3529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
Mingming Yine62d7842013-10-25 16:26:03 -07003531 if(audio_extn_compr_cap_enabled() &&
3532 audio_extn_compr_cap_format_supported(in->config.format))
3533 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003534
3535 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 return;
3537}
3538
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003539static int adev_dump(const audio_hw_device_t *device __unused,
3540 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541{
3542 return 0;
3543}
3544
3545static int adev_close(hw_device_t *device)
3546{
3547 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003548
3549 if (!adev)
3550 return 0;
3551
3552 pthread_mutex_lock(&adev_init_lock);
3553
3554 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003555 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003556 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003557 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003558 audio_route_free(adev->audio_route);
3559 free(adev->snd_dev_ref_cnt);
3560 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003561 free(device);
3562 adev = NULL;
3563 }
3564 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 return 0;
3566}
3567
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003568/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3569 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3570 * just that it _might_ work.
3571 */
3572static int period_size_is_plausible_for_low_latency(int period_size)
3573{
3574 switch (period_size) {
3575 case 160:
3576 case 240:
3577 case 320:
3578 case 480:
3579 return 1;
3580 default:
3581 return 0;
3582 }
3583}
3584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585static int adev_open(const hw_module_t *module, const char *name,
3586 hw_device_t **device)
3587{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003588 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003590 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3592
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003593 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003594 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003595 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003596 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003597 ALOGD("%s: returning existing instance of adev", __func__);
3598 ALOGD("%s: exit", __func__);
3599 pthread_mutex_unlock(&adev_init_lock);
3600 return 0;
3601 }
3602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 adev = calloc(1, sizeof(struct audio_device));
3604
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003605 if (!adev) {
3606 pthread_mutex_unlock(&adev_init_lock);
3607 return -ENOMEM;
3608 }
3609
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003610 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3613 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3614 adev->device.common.module = (struct hw_module_t *)module;
3615 adev->device.common.close = adev_close;
3616
3617 adev->device.init_check = adev_init_check;
3618 adev->device.set_voice_volume = adev_set_voice_volume;
3619 adev->device.set_master_volume = adev_set_master_volume;
3620 adev->device.get_master_volume = adev_get_master_volume;
3621 adev->device.set_master_mute = adev_set_master_mute;
3622 adev->device.get_master_mute = adev_get_master_mute;
3623 adev->device.set_mode = adev_set_mode;
3624 adev->device.set_mic_mute = adev_set_mic_mute;
3625 adev->device.get_mic_mute = adev_get_mic_mute;
3626 adev->device.set_parameters = adev_set_parameters;
3627 adev->device.get_parameters = adev_get_parameters;
3628 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3629 adev->device.open_output_stream = adev_open_output_stream;
3630 adev->device.close_output_stream = adev_close_output_stream;
3631 adev->device.open_input_stream = adev_open_input_stream;
3632 adev->device.close_input_stream = adev_close_input_stream;
3633 adev->device.dump = adev_dump;
3634
3635 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003637 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003638 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003641 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003642 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003643 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3644 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003645 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003646 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003647 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003648 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003649 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303650
3651 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3652 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003654 adev->platform = platform_init(adev);
3655 if (!adev->platform) {
3656 free(adev->snd_dev_ref_cnt);
3657 free(adev);
3658 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3659 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003660 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003661 return -EINVAL;
3662 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003663
Naresh Tanniru4c630392014-05-12 01:05:52 +05303664 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3665
Eric Laurentc4aef752013-09-12 17:45:53 -07003666 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3667 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3668 if (adev->visualizer_lib == NULL) {
3669 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3670 } else {
3671 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3672 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003673 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003674 "visualizer_hal_start_output");
3675 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003676 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003677 "visualizer_hal_stop_output");
3678 }
3679 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003680 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003681 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003682
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003683 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3684 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3685 if (adev->offload_effects_lib == NULL) {
3686 ALOGE("%s: DLOPEN failed for %s", __func__,
3687 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3688 } else {
3689 ALOGV("%s: DLOPEN successful for %s", __func__,
3690 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3691 adev->offload_effects_start_output =
3692 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3693 "offload_effects_bundle_hal_start_output");
3694 adev->offload_effects_stop_output =
3695 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3696 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003697 adev->offload_effects_set_hpx_state =
3698 (int (*)(bool))dlsym(adev->offload_effects_lib,
3699 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003700 }
3701 }
3702
Mingming Yin514a8bc2014-07-29 15:22:21 -07003703 adev->bt_wb_speech_enabled = false;
3704
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003705 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 *device = &adev->device.common;
3707
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003708 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3709 &adev->streams_output_cfg_list);
3710
Kiran Kandi910e1862013-10-29 13:29:42 -07003711 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003712
3713 char value[PROPERTY_VALUE_MAX];
3714 int trial;
3715 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3716 trial = atoi(value);
3717 if (period_size_is_plausible_for_low_latency(trial)) {
3718 pcm_config_low_latency.period_size = trial;
3719 pcm_config_low_latency.start_threshold = trial / 4;
3720 pcm_config_low_latency.avail_min = trial / 4;
3721 configured_low_latency_capture_period_size = trial;
3722 }
3723 }
3724 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3725 trial = atoi(value);
3726 if (period_size_is_plausible_for_low_latency(trial)) {
3727 configured_low_latency_capture_period_size = trial;
3728 }
3729 }
3730
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003731 pthread_mutex_unlock(&adev_init_lock);
3732
Eric Laurent994a6932013-07-17 11:51:42 -07003733 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 return 0;
3735}
3736
3737static struct hw_module_methods_t hal_module_methods = {
3738 .open = adev_open,
3739};
3740
3741struct audio_module HAL_MODULE_INFO_SYM = {
3742 .common = {
3743 .tag = HARDWARE_MODULE_TAG,
3744 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3745 .hal_api_version = HARDWARE_HAL_API_VERSION,
3746 .id = AUDIO_HARDWARE_MODULE_ID,
3747 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003748 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 .methods = &hal_module_methods,
3750 },
3751};