blob: 5bed2cf4b5a0c02c8e432e1ec6bf2789076a7432 [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 Naripeddy19dc03b2014-03-10 14:43:05 -0700421 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530422 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200572 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700573 audio_extn_sound_trigger_update_device_status(snd_device,
574 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530575 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800576 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 return 0;
580}
581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582static void check_usecases_codec_backend(struct audio_device *adev,
583 struct audio_usecase *uc_info,
584 snd_device_t snd_device)
585{
586 struct listnode *node;
587 struct audio_usecase *usecase;
588 bool switch_device[AUDIO_USECASE_MAX];
589 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530590 int backend_idx = DEFAULT_CODEC_BACKEND;
591 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592
593 /*
594 * This function is to make sure that all the usecases that are active on
595 * the hardware codec backend are always routed to any one device that is
596 * handled by the hardware codec.
597 * For example, if low-latency and deep-buffer usecases are currently active
598 * on speaker and out_set_parameters(headset) is received on low-latency
599 * output, then we have to make sure deep-buffer is also switched to headset,
600 * because of the limitation that both the devices cannot be enabled
601 * at the same time as they share the same backend.
602 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700603 /*
604 * This call is to check if we need to force routing for a particular stream
605 * If there is a backend configuration change for the device when a
606 * new stream starts, then ADM needs to be closed and re-opened with the new
607 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530608 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700609 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530610 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
611 snd_device);
612 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800614 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800615 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 for (i = 0; i < AUDIO_USECASE_MAX; i++)
617 switch_device[i] = false;
618
619 list_for_each(node, &adev->usecase_list) {
620 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530621
622 if (usecase == uc_info)
623 continue;
624 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
625 ALOGV("%s: backend_idx: %d,"
626 "usecase_backend_idx: %d, curr device: %s, usecase device:"
627 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530628 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530629
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800630 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700631 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
633 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530634 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700636 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700637 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 switch_device[usecase->id] = true;
639 num_uc_to_switch++;
640 }
641 }
642
643 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700644 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530646 /* Make sure the previous devices to be disabled first and then enable the
647 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 list_for_each(node, &adev->usecase_list) {
649 usecase = node_to_item(node, struct audio_usecase, list);
650 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700651 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 }
653 }
654
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700655 list_for_each(node, &adev->usecase_list) {
656 usecase = node_to_item(node, struct audio_usecase, list);
657 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700658 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700659 }
660 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 /* Re-route all the usecases on the shared backend other than the
663 specified usecase to new snd devices */
664 list_for_each(node, &adev->usecase_list) {
665 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530666 /* Update the out_snd_device only before enabling the audio route */
667 if (switch_device[usecase->id] ) {
668 usecase->out_snd_device = snd_device;
669 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530670 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 }
672 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 }
674}
675
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700676static void check_and_route_capture_usecases(struct audio_device *adev,
677 struct audio_usecase *uc_info,
678 snd_device_t snd_device)
679{
680 struct listnode *node;
681 struct audio_usecase *usecase;
682 bool switch_device[AUDIO_USECASE_MAX];
683 int i, num_uc_to_switch = 0;
684
685 /*
686 * This function is to make sure that all the active capture usecases
687 * are always routed to the same input sound device.
688 * For example, if audio-record and voice-call usecases are currently
689 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
690 * is received for voice call then we have to make sure that audio-record
691 * usecase is also switched to earpiece i.e. voice-dmic-ef,
692 * because of the limitation that two devices cannot be enabled
693 * at the same time if they share the same backend.
694 */
695 for (i = 0; i < AUDIO_USECASE_MAX; i++)
696 switch_device[i] = false;
697
698 list_for_each(node, &adev->usecase_list) {
699 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800700 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700702 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700703 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530704 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
705 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700706 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
708 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700709 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700710 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711 switch_device[usecase->id] = true;
712 num_uc_to_switch++;
713 }
714 }
715
716 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700717 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530719 /* Make sure the previous devices to be disabled first and then enable the
720 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700724 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800725 }
726 }
727
728 list_for_each(node, &adev->usecase_list) {
729 usecase = node_to_item(node, struct audio_usecase, list);
730 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700731 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 }
733 }
734
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735 /* Re-route all the usecases on the shared backend other than the
736 specified usecase to new snd devices */
737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 /* Update the in_snd_device only before enabling the audio route */
740 if (switch_device[usecase->id] ) {
741 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800742 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530743 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744 }
745 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746 }
747}
748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700750static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700752 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700753 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754
755 switch (channels) {
756 /*
757 * Do not handle stereo output in Multi-channel cases
758 * Stereo case is handled in normal playback path
759 */
760 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767 break;
768 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700769 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 break;
777 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700778 ALOGE("HDMI does not support multi channel playback");
779 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780 break;
781 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700782 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783}
784
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800785audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
786 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700787{
788 struct audio_usecase *usecase;
789 struct listnode *node;
790
791 list_for_each(node, &adev->usecase_list) {
792 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800793 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700794 ALOGV("%s: usecase id %d", __func__, usecase->id);
795 return usecase->id;
796 }
797 }
798 return USECASE_INVALID;
799}
800
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700801struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700802 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
809 if (usecase->id == uc_id)
810 return usecase;
811 }
812 return NULL;
813}
814
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800817 snd_device_t out_snd_device = SND_DEVICE_NONE;
818 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 struct audio_usecase *usecase = NULL;
820 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800821 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800822 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800823 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800824 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 usecase = get_usecase_from_list(adev, uc_id);
828 if (usecase == NULL) {
829 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
830 return -EINVAL;
831 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800833 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800834 (usecase->type == VOIP_CALL) ||
835 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700836 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800837 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700838 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 usecase->devices = usecase->stream.out->devices;
840 } else {
841 /*
842 * If the voice call is active, use the sound devices of voice call usecase
843 * so that it would not result any device switch. All the usecases will
844 * be switched to new device when select_devices() is called for voice call
845 * usecase. This is to avoid switching devices for voice call when
846 * check_usecases_codec_backend() is called below.
847 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700848 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700849 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800850 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700851 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
852 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 in_snd_device = vc_usecase->in_snd_device;
854 out_snd_device = vc_usecase->out_snd_device;
855 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800856 } else if (voice_extn_compress_voip_is_active(adev)) {
857 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700858 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530859 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800861 in_snd_device = voip_usecase->in_snd_device;
862 out_snd_device = voip_usecase->out_snd_device;
863 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800864 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800865 hfp_ucid = audio_extn_hfp_get_usecase();
866 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800868 in_snd_device = hfp_usecase->in_snd_device;
869 out_snd_device = hfp_usecase->out_snd_device;
870 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 }
872 if (usecase->type == PCM_PLAYBACK) {
873 usecase->devices = usecase->stream.out->devices;
874 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700875 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700876 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800877 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700878 if (usecase->stream.out == adev->primary_output &&
879 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800880 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 select_devices(adev, adev->active_input->usecase);
882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 } else if (usecase->type == PCM_CAPTURE) {
885 usecase->devices = usecase->stream.in->device;
886 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700887 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530889 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
890 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
891 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
892 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700893 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi50650f42015-07-06 15:07:14 -0700894 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700895 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
896 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700898 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 }
901 }
902
903 if (out_snd_device == usecase->out_snd_device &&
904 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 return 0;
906 }
907
sangwoobc677242013-08-08 16:53:43 +0900908 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700909 out_snd_device, platform_get_snd_device_name(out_snd_device),
910 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 /*
913 * Limitation: While in call, to do a device switch we need to disable
914 * and enable both RX and TX devices though one of them is same as current
915 * device.
916 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700917 if ((usecase->type == VOICE_CALL) &&
918 (usecase->in_snd_device != SND_DEVICE_NONE) &&
919 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700920 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella082e8e92015-08-14 18:00:08 -0700921 }
922
923 if (((usecase->type == VOICE_CALL) ||
924 (usecase->type == VOIP_CALL)) &&
925 (usecase->out_snd_device != SND_DEVICE_NONE)) {
926 /* Disable sidetone only if voice/voip call already exists */
927 if (voice_is_call_state_active(adev) ||
928 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700929 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800930 }
931
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 /* Disable current sound devices */
933 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700934 disable_audio_route(adev, usecase);
935 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800936 }
937
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700938 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700939 disable_audio_route(adev, usecase);
940 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 }
942
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800943 /* Applicable only on the targets that has external modem.
944 * New device information should be sent to modem before enabling
945 * the devices to reduce in-call device switch time.
946 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700947 if ((usecase->type == VOICE_CALL) &&
948 (usecase->in_snd_device != SND_DEVICE_NONE) &&
949 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800950 status = platform_switch_voice_call_enable_device_config(adev->platform,
951 out_snd_device,
952 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700953 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800954
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955 /* Enable new sound devices */
956 if (out_snd_device != SND_DEVICE_NONE) {
957 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
958 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700959 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800960 }
961
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700962 if (in_snd_device != SND_DEVICE_NONE) {
963 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966
Avinash Vaish71a8b972014-07-24 15:36:33 +0530967 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700968 status = platform_switch_voice_call_device_post(adev->platform,
969 out_snd_device,
970 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530971 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella082e8e92015-08-14 18:00:08 -0700972 /* Enable sidetone only if voice/voip call already exists */
973 if (voice_is_call_state_active(adev) ||
974 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700975 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530976 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800977
sangwoo170731f2013-06-08 15:36:36 +0900978 usecase->in_snd_device = in_snd_device;
979 usecase->out_snd_device = out_snd_device;
980
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530981 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700982 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530983 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700984 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530985 usecase->stream.out->flags,
986 usecase->stream.out->format,
987 usecase->stream.out->sample_rate,
988 usecase->stream.out->bit_width,
989 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700990 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530991 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700992
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700993 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900994
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800995 /* Applicable only on the targets that has external modem.
996 * Enable device command should be sent to modem only after
997 * enabling voice call mixer controls
998 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700999 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001000 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1001 out_snd_device,
1002 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301003 ALOGD("%s: done",__func__);
1004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 return status;
1006}
1007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008static int stop_input_stream(struct stream_in *in)
1009{
1010 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001011 struct audio_usecase *uc_info;
1012 struct audio_device *adev = in->dev;
1013
Eric Laurentc8400632013-02-14 19:04:54 -08001014 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015
Eric Laurent994a6932013-07-17 11:51:42 -07001016 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 uc_info = get_usecase_from_list(adev, in->usecase);
1019 if (uc_info == NULL) {
1020 ALOGE("%s: Could not find the usecase (%d) in the list",
1021 __func__, in->usecase);
1022 return -EINVAL;
1023 }
1024
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001025 /* Close in-call recording streams */
1026 voice_check_and_stop_incall_rec_usecase(adev, in);
1027
Eric Laurent150dbfe2013-02-27 14:31:02 -08001028 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001029 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030
1031 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001032 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001034 list_remove(&uc_info->list);
1035 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036
Eric Laurent994a6932013-07-17 11:51:42 -07001037 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 return ret;
1039}
1040
1041int start_input_stream(struct stream_in *in)
1042{
1043 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001044 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 struct audio_usecase *uc_info;
1046 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301047 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048
Mingming Yine62d7842013-10-25 16:26:03 -07001049 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301050 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1051 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001052
Naresh Tanniru80659832014-06-04 18:17:56 +05301053
1054 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301055 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301056 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301057 goto error_config;
1058 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301059
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001060 /* Check if source matches incall recording usecase criteria */
1061 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1062 if (ret)
1063 goto error_config;
1064 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001065 ALOGD("%s: Updated usecase(%d: %s)",
1066 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001067
Eric Laurentb23d5282013-05-14 15:27:20 -07001068 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 if (in->pcm_device_id < 0) {
1070 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1071 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001072 ret = -EINVAL;
1073 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001075
1076 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001078
1079 if (!uc_info) {
1080 ret = -ENOMEM;
1081 goto error_config;
1082 }
1083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 uc_info->id = in->usecase;
1085 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001086 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 uc_info->devices = in->device;
1088 uc_info->in_snd_device = SND_DEVICE_NONE;
1089 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001091 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301092 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094
Eric Laurentc8400632013-02-14 19:04:54 -08001095 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001096 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1097
1098 unsigned int flags = PCM_IN;
1099 unsigned int pcm_open_retry_count = 0;
1100
1101 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1102 flags |= PCM_MMAP | PCM_NOIRQ;
1103 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1104 }
1105
1106 while (1) {
1107 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1108 flags, &in->config);
1109 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1110 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1111 if (in->pcm != NULL) {
1112 pcm_close(in->pcm);
1113 in->pcm = NULL;
1114 }
1115 if (pcm_open_retry_count-- == 0) {
1116 ret = -EIO;
1117 goto error_open;
1118 }
1119 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1120 continue;
1121 }
1122 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301124 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301125
Eric Laurent994a6932013-07-17 11:51:42 -07001126 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001127 return ret;
1128
1129error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301131 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001132
1133error_config:
1134 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001136
1137 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138}
1139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001140/* must be called with out->lock locked */
1141static int send_offload_cmd_l(struct stream_out* out, int command)
1142{
1143 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1144
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001145 if (!cmd) {
1146 ALOGE("failed to allocate mem for command 0x%x", command);
1147 return -ENOMEM;
1148 }
1149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001150 ALOGVV("%s %d", __func__, command);
1151
1152 cmd->cmd = command;
1153 list_add_tail(&out->offload_cmd_list, &cmd->node);
1154 pthread_cond_signal(&out->offload_cond);
1155 return 0;
1156}
1157
1158/* must be called iwth out->lock locked */
1159static void stop_compressed_output_l(struct stream_out *out)
1160{
1161 out->offload_state = OFFLOAD_STATE_IDLE;
1162 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001163 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001164 if (out->compr != NULL) {
1165 compress_stop(out->compr);
1166 while (out->offload_thread_blocked) {
1167 pthread_cond_wait(&out->cond, &out->lock);
1168 }
1169 }
1170}
1171
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001172bool is_offload_usecase(audio_usecase_t uc_id)
1173{
1174 unsigned int i;
1175 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1176 if (uc_id == offload_usecases[i])
1177 return true;
1178 }
1179 return false;
1180}
1181
1182static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1183{
1184 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1185 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1186 char value[PROPERTY_VALUE_MAX] = {0};
1187
1188 property_get("audio.offload.multiple.enabled", value, NULL);
1189 if (!(atoi(value) || !strncmp("true", value, 4)))
1190 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1191
1192 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1193 for (i = 0; i < num_usecase; i++) {
1194 if (!(adev->offload_usecases_state & (0x1<<i))) {
1195 adev->offload_usecases_state |= 0x1 << i;
1196 ret = offload_usecases[i];
1197 break;
1198 }
1199 }
1200 ALOGV("%s: offload usecase is %d", __func__, ret);
1201 return ret;
1202}
1203
1204static void free_offload_usecase(struct audio_device *adev,
1205 audio_usecase_t uc_id)
1206{
1207 unsigned int i;
1208 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1209 if (offload_usecases[i] == uc_id) {
1210 adev->offload_usecases_state &= ~(0x1<<i);
1211 break;
1212 }
1213 }
1214 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1215}
1216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217static void *offload_thread_loop(void *context)
1218{
1219 struct stream_out *out = (struct stream_out *) context;
1220 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001221 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1224 set_sched_policy(0, SP_FOREGROUND);
1225 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1226
1227 ALOGV("%s", __func__);
1228 pthread_mutex_lock(&out->lock);
1229 for (;;) {
1230 struct offload_cmd *cmd = NULL;
1231 stream_callback_event_t event;
1232 bool send_callback = false;
1233
1234 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1235 __func__, list_empty(&out->offload_cmd_list),
1236 out->offload_state);
1237 if (list_empty(&out->offload_cmd_list)) {
1238 ALOGV("%s SLEEPING", __func__);
1239 pthread_cond_wait(&out->offload_cond, &out->lock);
1240 ALOGV("%s RUNNING", __func__);
1241 continue;
1242 }
1243
1244 item = list_head(&out->offload_cmd_list);
1245 cmd = node_to_item(item, struct offload_cmd, node);
1246 list_remove(item);
1247
1248 ALOGVV("%s STATE %d CMD %d out->compr %p",
1249 __func__, out->offload_state, cmd->cmd, out->compr);
1250
1251 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1252 free(cmd);
1253 break;
1254 }
1255
1256 if (out->compr == NULL) {
1257 ALOGE("%s: Compress handle is NULL", __func__);
1258 pthread_cond_signal(&out->cond);
1259 continue;
1260 }
1261 out->offload_thread_blocked = true;
1262 pthread_mutex_unlock(&out->lock);
1263 send_callback = false;
1264 switch(cmd->cmd) {
1265 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001266 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001267 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001268 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001269 send_callback = true;
1270 event = STREAM_CBK_EVENT_WRITE_READY;
1271 break;
1272 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001273 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301274 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001275 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301276 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001277 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301278 if (ret < 0)
1279 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301280 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301281 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001282 compress_drain(out->compr);
1283 else
1284 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301285 if (ret != -ENETRESET) {
1286 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301287 pthread_mutex_lock(&out->lock);
1288 out->send_new_metadata = 1;
1289 out->send_next_track_params = true;
1290 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301291 event = STREAM_CBK_EVENT_DRAIN_READY;
1292 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1293 } else
1294 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295 break;
1296 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001297 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001298 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001299 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300 send_callback = true;
1301 event = STREAM_CBK_EVENT_DRAIN_READY;
1302 break;
1303 default:
1304 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1305 break;
1306 }
1307 pthread_mutex_lock(&out->lock);
1308 out->offload_thread_blocked = false;
1309 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001310 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001311 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001313 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 free(cmd);
1315 }
1316
1317 pthread_cond_signal(&out->cond);
1318 while (!list_empty(&out->offload_cmd_list)) {
1319 item = list_head(&out->offload_cmd_list);
1320 list_remove(item);
1321 free(node_to_item(item, struct offload_cmd, node));
1322 }
1323 pthread_mutex_unlock(&out->lock);
1324
1325 return NULL;
1326}
1327
1328static int create_offload_callback_thread(struct stream_out *out)
1329{
1330 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1331 list_init(&out->offload_cmd_list);
1332 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1333 offload_thread_loop, out);
1334 return 0;
1335}
1336
1337static int destroy_offload_callback_thread(struct stream_out *out)
1338{
1339 pthread_mutex_lock(&out->lock);
1340 stop_compressed_output_l(out);
1341 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1342
1343 pthread_mutex_unlock(&out->lock);
1344 pthread_join(out->offload_thread, (void **) NULL);
1345 pthread_cond_destroy(&out->offload_cond);
1346
1347 return 0;
1348}
1349
Eric Laurent07eeafd2013-10-06 12:52:49 -07001350static bool allow_hdmi_channel_config(struct audio_device *adev)
1351{
1352 struct listnode *node;
1353 struct audio_usecase *usecase;
1354 bool ret = true;
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 usecase = node_to_item(node, struct audio_usecase, list);
1358 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1359 /*
1360 * If voice call is already existing, do not proceed further to avoid
1361 * disabling/enabling both RX and TX devices, CSD calls, etc.
1362 * Once the voice call done, the HDMI channels can be configured to
1363 * max channels of remaining use cases.
1364 */
1365 if (usecase->id == USECASE_VOICE_CALL) {
1366 ALOGD("%s: voice call is active, no change in HDMI channels",
1367 __func__);
1368 ret = false;
1369 break;
1370 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1371 ALOGD("%s: multi channel playback is active, "
1372 "no change in HDMI channels", __func__);
1373 ret = false;
1374 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001375 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001376 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001377 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1378 ", no change in HDMI channels", __func__,
1379 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001380 ret = false;
1381 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001382 }
1383 }
1384 }
1385 return ret;
1386}
1387
1388static int check_and_set_hdmi_channels(struct audio_device *adev,
1389 unsigned int channels)
1390{
1391 struct listnode *node;
1392 struct audio_usecase *usecase;
1393
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001394 unsigned int supported_channels = platform_edid_get_max_channels(
1395 adev->platform);
1396 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397 /* Check if change in HDMI channel config is allowed */
1398 if (!allow_hdmi_channel_config(adev))
1399 return 0;
1400
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001401 if (channels > supported_channels)
1402 channels = supported_channels;
1403
Eric Laurent07eeafd2013-10-06 12:52:49 -07001404 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001405 ALOGD("%s: Requested channels are same as current channels(%d)",
1406 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001407 return 0;
1408 }
1409
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001410 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001411 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001412 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 adev->cur_hdmi_channels = channels;
1414
1415 /*
1416 * Deroute all the playback streams routed to HDMI so that
1417 * the back end is deactivated. Note that backend will not
1418 * be deactivated if any one stream is connected to it.
1419 */
1420 list_for_each(node, &adev->usecase_list) {
1421 usecase = node_to_item(node, struct audio_usecase, list);
1422 if (usecase->type == PCM_PLAYBACK &&
1423 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001424 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425 }
1426 }
1427
1428 /*
1429 * Enable all the streams disabled above. Now the HDMI backend
1430 * will be activated with new channel configuration
1431 */
1432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
1434 if (usecase->type == PCM_PLAYBACK &&
1435 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001436 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001437 }
1438 }
1439
1440 return 0;
1441}
1442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443static int stop_output_stream(struct stream_out *out)
1444{
1445 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 struct audio_usecase *uc_info;
1447 struct audio_device *adev = out->dev;
1448
Eric Laurent994a6932013-07-17 11:51:42 -07001449 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001450 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 uc_info = get_usecase_from_list(adev, out->usecase);
1452 if (uc_info == NULL) {
1453 ALOGE("%s: Could not find the usecase (%d) in the list",
1454 __func__, out->usecase);
1455 return -EINVAL;
1456 }
1457
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001458 if (is_offload_usecase(out->usecase) &&
1459 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001460 if (adev->visualizer_stop_output != NULL)
1461 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001462
1463 audio_extn_dts_remove_state_notifier_node(out->usecase);
1464
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001465 if (adev->offload_effects_stop_output != NULL)
1466 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1467 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001468
Eric Laurent150dbfe2013-02-27 14:31:02 -08001469 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001470 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471
1472 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001473 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001475 list_remove(&uc_info->list);
1476 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001478 if (is_offload_usecase(out->usecase) &&
1479 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1480 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1481 ALOGV("Disable passthrough , reset mixer to pcm");
1482 /* NO_PASSTHROUGH */
1483 out->compr_config.codec->compr_passthr = 0;
1484 audio_extn_dolby_set_hdmi_config(adev, out);
1485 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1486 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001487 /* Must be called after removing the usecase from list */
1488 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1489 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1490
Eric Laurent994a6932013-07-17 11:51:42 -07001491 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492 return ret;
1493}
1494
1495int start_output_stream(struct stream_out *out)
1496{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001498 int sink_channels = 0;
1499 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500 struct audio_usecase *uc_info;
1501 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301502 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001504 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1505 ret = -EINVAL;
1506 goto error_config;
1507 }
1508
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301509 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1510 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1511 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301512
Naresh Tanniru80659832014-06-04 18:17:56 +05301513 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301514 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301515 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301516 goto error_config;
1517 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301518
Eric Laurentb23d5282013-05-14 15:27:20 -07001519 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520 if (out->pcm_device_id < 0) {
1521 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1522 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001523 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001524 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 }
1526
1527 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001528
1529 if (!uc_info) {
1530 ret = -ENOMEM;
1531 goto error_config;
1532 }
1533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 uc_info->id = out->usecase;
1535 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001536 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537 uc_info->devices = out->devices;
1538 uc_info->in_snd_device = SND_DEVICE_NONE;
1539 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001540 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001541 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001542 if (is_offload_usecase(out->usecase)) {
1543 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001544 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1545 }
1546 }
Mingming Yin9c041392014-05-01 15:37:31 -07001547 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1548 if (!strncmp("true", prop_value, 4)) {
1549 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001550 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1551 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001552 check_and_set_hdmi_channels(adev, sink_channels);
1553 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001554 if (is_offload_usecase(out->usecase)) {
1555 unsigned int ch_count = out->compr_config.codec->ch_in;
1556 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1557 /* backend channel config for passthrough stream is stereo */
1558 ch_count = 2;
1559 check_and_set_hdmi_channels(adev, ch_count);
1560 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001561 check_and_set_hdmi_channels(adev, out->config.channels);
1562 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001563 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001564 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001565 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 select_devices(adev, out->usecase);
1568
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001569 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1570 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001571 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001572 unsigned int flags = PCM_OUT;
1573 unsigned int pcm_open_retry_count = 0;
1574 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1575 flags |= PCM_MMAP | PCM_NOIRQ;
1576 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1577 } else
1578 flags |= PCM_MONOTONIC;
1579
1580 while (1) {
1581 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1582 flags, &out->config);
1583 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1584 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1585 if (out->pcm != NULL) {
1586 pcm_close(out->pcm);
1587 out->pcm = NULL;
1588 }
1589 if (pcm_open_retry_count-- == 0) {
1590 ret = -EIO;
1591 goto error_open;
1592 }
1593 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1594 continue;
1595 }
1596 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001597 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001598 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1599 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001600 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001601 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1602 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001604 out->compr = compress_open(adev->snd_card,
1605 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 COMPRESS_IN, &out->compr_config);
1607 if (out->compr && !is_compress_ready(out->compr)) {
1608 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1609 compress_close(out->compr);
1610 out->compr = NULL;
1611 ret = -EIO;
1612 goto error_open;
1613 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301614 /* compress_open sends params of the track, so reset the flag here */
1615 out->is_compr_metadata_avail = false;
1616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 if (out->offload_callback)
1618 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001619
Fred Oh3f43e742015-03-04 18:42:34 -08001620 /* Since small bufs uses blocking writes, a write will be blocked
1621 for the default max poll time (20s) in the event of an SSR.
1622 Reduce the poll time to observe and deal with SSR faster.
1623 */
1624 if (out->use_small_bufs) {
1625 compress_set_max_poll_wait(out->compr, 1000);
1626 }
1627
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001628 audio_extn_dts_create_state_notifier_node(out->usecase);
1629 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1630 popcount(out->channel_mask),
1631 out->playback_started);
1632
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001633#ifdef DS1_DOLBY_DDP_ENABLED
1634 if (audio_extn_is_dolby_format(out->format))
1635 audio_extn_dolby_send_ddp_endp_params(adev);
1636#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001637 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1638 if (adev->visualizer_start_output != NULL)
1639 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1640 if (adev->offload_effects_start_output != NULL)
1641 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001642 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001643 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 }
Eric Laurent994a6932013-07-17 11:51:42 -07001645 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001649error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651}
1652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653static int check_input_parameters(uint32_t sample_rate,
1654 audio_format_t format,
1655 int channel_count)
1656{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001657 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001659 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001660 !voice_extn_compress_voip_is_format_supported(format) &&
1661 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001662
1663 switch (channel_count) {
1664 case 1:
1665 case 2:
1666 case 6:
1667 break;
1668 default:
1669 ret = -EINVAL;
1670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671
1672 switch (sample_rate) {
1673 case 8000:
1674 case 11025:
1675 case 12000:
1676 case 16000:
1677 case 22050:
1678 case 24000:
1679 case 32000:
1680 case 44100:
1681 case 48000:
1682 break;
1683 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001684 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685 }
1686
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001687 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688}
1689
1690static size_t get_input_buffer_size(uint32_t sample_rate,
1691 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001692 int channel_count,
1693 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694{
1695 size_t size = 0;
1696
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001697 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1698 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001700 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001701 if (is_low_latency)
1702 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001703 /* ToDo: should use frame_size computed based on the format and
1704 channel_count here. */
1705 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001707 /* make sure the size is multiple of 32 bytes
1708 * At 48 kHz mono 16-bit PCM:
1709 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1710 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1711 */
1712 size += 0x1f;
1713 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001714
1715 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716}
1717
1718static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1719{
1720 struct stream_out *out = (struct stream_out *)stream;
1721
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723}
1724
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001725static int out_set_sample_rate(struct audio_stream *stream __unused,
1726 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727{
1728 return -ENOSYS;
1729}
1730
1731static size_t out_get_buffer_size(const struct audio_stream *stream)
1732{
1733 struct stream_out *out = (struct stream_out *)stream;
1734
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001735 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001736 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001737 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1738 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001740 return out->config.period_size *
1741 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742}
1743
1744static uint32_t out_get_channels(const struct audio_stream *stream)
1745{
1746 struct stream_out *out = (struct stream_out *)stream;
1747
1748 return out->channel_mask;
1749}
1750
1751static audio_format_t out_get_format(const struct audio_stream *stream)
1752{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 struct stream_out *out = (struct stream_out *)stream;
1754
1755 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756}
1757
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001758static int out_set_format(struct audio_stream *stream __unused,
1759 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760{
1761 return -ENOSYS;
1762}
1763
1764static int out_standby(struct audio_stream *stream)
1765{
1766 struct stream_out *out = (struct stream_out *)stream;
1767 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301769 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1770 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001771 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1772 /* Ignore standby in case of voip call because the voip output
1773 * stream is closed in adev_close_output_stream()
1774 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301775 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001776 return 0;
1777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001781 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001783 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 if (out->pcm) {
1785 pcm_close(out->pcm);
1786 out->pcm = NULL;
1787 }
1788 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001789 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001790 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301791 out->send_next_track_params = false;
1792 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 out->gapless_mdata.encoder_delay = 0;
1794 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 if (out->compr != NULL) {
1796 compress_close(out->compr);
1797 out->compr = NULL;
1798 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001799 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 }
1803 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001804 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 return 0;
1806}
1807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001808static int out_dump(const struct audio_stream *stream __unused,
1809 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810{
1811 return 0;
1812}
1813
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1815{
1816 int ret = 0;
1817 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001818
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 return -EINVAL;
1822 }
1823
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001824 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1825 if (ret >= 0) {
1826 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1827 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1828 ALOGV("ADTS format is set in offload mode");
1829 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001830 }
1831
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301832 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001833
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1835 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301836 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001837 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1839 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301840 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001841 }
1842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843 ALOGV("%s new encoder delay %u and padding %u", __func__,
1844 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1845
1846 return 0;
1847}
1848
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001849static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1850{
1851 return out == adev->primary_output || out == adev->voice_tx_output;
1852}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1855{
1856 struct stream_out *out = (struct stream_out *)stream;
1857 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001858 struct audio_usecase *usecase;
1859 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 struct str_parms *parms;
1861 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001862 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001863 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
sangwoobc677242013-08-08 16:53:43 +09001865 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001866 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301868 if (!parms)
1869 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001870 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1871 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001874 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301877 * When HDMI cable is unplugged/usb hs is disconnected the
1878 * music playback is paused and the policy manager sends routing=0
1879 * But the audioflingercontinues to write data until standby time
1880 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 * Avoid this by routing audio to speaker until standby.
1882 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301883 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1884 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001886 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1887 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 }
1889
1890 /*
1891 * select_devices() call below switches all the usecases on the same
1892 * backend to the new device. Refer to check_usecases_codec_backend() in
1893 * the select_devices(). But how do we undo this?
1894 *
1895 * For example, music playback is active on headset (deep-buffer usecase)
1896 * and if we go to ringtones and select a ringtone, low-latency usecase
1897 * will be started on headset+speaker. As we can't enable headset+speaker
1898 * and headset devices at the same time, select_devices() switches the music
1899 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1900 * So when the ringtone playback is completed, how do we undo the same?
1901 *
1902 * We are relying on the out_set_parameters() call on deep-buffer output,
1903 * once the ringtone playback is ended.
1904 * NOTE: We should not check if the current devices are same as new devices.
1905 * Because select_devices() must be called to switch back the music
1906 * playback to headset.
1907 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001908 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909 out->devices = val;
1910
1911 if (!out->standby)
1912 select_devices(adev, out->usecase);
1913
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001914 if (output_drives_call(adev, out)) {
1915 if(!voice_is_in_call(adev)) {
1916 if (adev->mode == AUDIO_MODE_IN_CALL) {
1917 adev->current_call_output = out;
1918 ret = voice_start_call(adev);
1919 }
1920 } else {
1921 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001922 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001923 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001924 }
1925 }
1926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001928 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001930
1931 if (out == adev->primary_output) {
1932 pthread_mutex_lock(&adev->lock);
1933 audio_extn_set_parameters(adev, parms);
1934 pthread_mutex_unlock(&adev->lock);
1935 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001936 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001937 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001939
1940 audio_extn_dts_create_state_notifier_node(out->usecase);
1941 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1942 popcount(out->channel_mask),
1943 out->playback_started);
1944
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001945 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001946 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301949error:
Eric Laurent994a6932013-07-17 11:51:42 -07001950 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 return ret;
1952}
1953
1954static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1955{
1956 struct stream_out *out = (struct stream_out *)stream;
1957 struct str_parms *query = str_parms_create_str(keys);
1958 char *str;
1959 char value[256];
1960 struct str_parms *reply = str_parms_create();
1961 size_t i, j;
1962 int ret;
1963 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001964
1965 if (!query || !reply) {
1966 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1967 return NULL;
1968 }
1969
Eric Laurent994a6932013-07-17 11:51:42 -07001970 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1972 if (ret >= 0) {
1973 value[0] = '\0';
1974 i = 0;
1975 while (out->supported_channel_masks[i] != 0) {
1976 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1977 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1978 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001979 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001981 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 first = false;
1983 break;
1984 }
1985 }
1986 i++;
1987 }
1988 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1989 str = str_parms_to_str(reply);
1990 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001991 voice_extn_out_get_parameters(out, query, reply);
1992 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001993 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001994 free(str);
1995 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001998
1999 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2000 if (ret >= 0) {
2001 value[0] = '\0';
2002 i = 0;
2003 first = true;
2004 while (out->supported_formats[i] != 0) {
2005 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2006 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2007 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002008 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002009 }
2010 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2011 first = false;
2012 break;
2013 }
2014 }
2015 i++;
2016 }
2017 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2018 str = str_parms_to_str(reply);
2019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 str_parms_destroy(query);
2021 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002022 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 return str;
2024}
2025
2026static uint32_t out_get_latency(const struct audio_stream_out *stream)
2027{
2028 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002029 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030
Alexy Josephaa54c872014-12-03 02:46:47 -08002031 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002032 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002033 } else {
2034 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002036 }
2037
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302038 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002039 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040}
2041
2042static int out_set_volume(struct audio_stream_out *stream, float left,
2043 float right)
2044{
Eric Laurenta9024de2013-04-04 09:19:12 -07002045 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002046 int volume[2];
2047
Eric Laurenta9024de2013-04-04 09:19:12 -07002048 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2049 /* only take left channel into account: the API is for stereo anyway */
2050 out->muted = (left == 0.0f);
2051 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002052 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002053 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2054 /*
2055 * Set mute or umute on HDMI passthrough stream.
2056 * Only take left channel into account.
2057 * Mute is 0 and unmute 1
2058 */
2059 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2060 } else {
2061 char mixer_ctl_name[128];
2062 struct audio_device *adev = out->dev;
2063 struct mixer_ctl *ctl;
2064 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002065 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002067 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2068 "Compress Playback %d Volume", pcm_device_id);
2069 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2070 if (!ctl) {
2071 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2072 __func__, mixer_ctl_name);
2073 return -EINVAL;
2074 }
2075 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2076 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2077 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2078 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002080 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 return -ENOSYS;
2083}
2084
2085static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2086 size_t bytes)
2087{
2088 struct stream_out *out = (struct stream_out *)stream;
2089 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302090 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002091 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302094
Naresh Tanniru80659832014-06-04 18:17:56 +05302095 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002096 // increase written size during SSR to avoid mismatch
2097 // with the written frames count in AF
2098 if (!is_offload_usecase(out->usecase))
2099 out->written += bytes / (out->config.channels * sizeof(short));
2100
Naresh Tanniru80659832014-06-04 18:17:56 +05302101 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302102 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302103 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302104 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002105 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302106 //during SSR for compress usecase we should return error to flinger
2107 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2108 pthread_mutex_unlock(&out->lock);
2109 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302110 }
2111 }
2112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002114 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002115 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002116 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2117 ret = voice_extn_compress_voip_start_output_stream(out);
2118 else
2119 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002123 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 goto exit;
2125 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302128 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2129 setChannelStatus(out, buffer, bytes);
2130 adev->mChannelStatusSet = true;
2131 }
2132
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002133 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002134 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002135 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002136 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002137 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2138 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302139 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2140 ALOGD("copl(%p):send next track params in gapless", out);
2141 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2142 out->send_next_track_params = false;
2143 out->is_compr_metadata_avail = false;
2144 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002145 }
2146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302148 if (ret < 0)
2149 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002151 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302152 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 } else if (-ENETRESET == ret) {
2155 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2156 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2157 pthread_mutex_unlock(&out->lock);
2158 out_standby(&out->stream.common);
2159 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302161 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002163 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 out->playback_started = 1;
2165 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002166
2167 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2168 popcount(out->channel_mask),
2169 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002170 }
2171 pthread_mutex_unlock(&out->lock);
2172 return ret;
2173 } else {
2174 if (out->pcm) {
2175 if (out->muted)
2176 memset((void *)buffer, 0, bytes);
2177 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002178 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2179 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2180 else
2181 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302182 if (ret < 0)
2183 ret = -errno;
2184 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002185 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 }
2188
2189exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302190 /* ToDo: There may be a corner case when SSR happens back to back during
2191 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302192 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302193 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302194 }
2195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 pthread_mutex_unlock(&out->lock);
2197
2198 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002199 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002200 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302201 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302202 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302203 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302204 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302205 out->standby = true;
2206 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002208 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302209 out_get_sample_rate(&out->stream.common));
2210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 }
2212 return bytes;
2213}
2214
2215static int out_get_render_position(const struct audio_stream_out *stream,
2216 uint32_t *dsp_frames)
2217{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302219 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002220
2221 if (dsp_frames == NULL)
2222 return -EINVAL;
2223
2224 *dsp_frames = 0;
2225 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002226 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002227 pthread_mutex_lock(&out->lock);
2228 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302231 if (ret < 0)
2232 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233 ALOGVV("%s rendered frames %d sample_rate %d",
2234 __func__, *dsp_frames, out->sample_rate);
2235 }
2236 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302237 if (-ENETRESET == ret) {
2238 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2239 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2240 return -EINVAL;
2241 } else if(ret < 0) {
2242 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2243 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302244 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2245 /*
2246 * Handle corner case where compress session is closed during SSR
2247 * and timestamp is queried
2248 */
2249 ALOGE(" ERROR: sound card not active, return error");
2250 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302251 } else {
2252 return 0;
2253 }
Zhou Song32a556e2015-05-05 10:46:56 +08002254 } else if (audio_is_linear_pcm(out->format)) {
2255 *dsp_frames = out->written;
2256 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 } else
2258 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259}
2260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002261static int out_add_audio_effect(const struct audio_stream *stream __unused,
2262 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263{
2264 return 0;
2265}
2266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002267static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2268 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269{
2270 return 0;
2271}
2272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002273static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2274 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275{
2276 return -EINVAL;
2277}
2278
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002279static int out_get_presentation_position(const struct audio_stream_out *stream,
2280 uint64_t *frames, struct timespec *timestamp)
2281{
2282 struct stream_out *out = (struct stream_out *)stream;
2283 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002284 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002285
2286 pthread_mutex_lock(&out->lock);
2287
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002288 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002289 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302290 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002291 &out->sample_rate);
2292 ALOGVV("%s rendered frames %ld sample_rate %d",
2293 __func__, dsp_frames, out->sample_rate);
2294 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302295 if (ret < 0)
2296 ret = -errno;
2297 if (-ENETRESET == ret) {
2298 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2299 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2300 ret = -EINVAL;
2301 } else
2302 ret = 0;
2303
Eric Laurent949a0892013-09-20 09:20:13 -07002304 /* this is the best we can do */
2305 clock_gettime(CLOCK_MONOTONIC, timestamp);
2306 }
2307 } else {
2308 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002309 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002310 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2311 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002312 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002313 // This adjustment accounts for buffering after app processor.
2314 // It is based on estimated DSP latency per use case, rather than exact.
2315 signed_frames -=
2316 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2317
Eric Laurent949a0892013-09-20 09:20:13 -07002318 // It would be unusual for this value to be negative, but check just in case ...
2319 if (signed_frames >= 0) {
2320 *frames = signed_frames;
2321 ret = 0;
2322 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002323 }
2324 }
2325 }
2326
2327 pthread_mutex_unlock(&out->lock);
2328
2329 return ret;
2330}
2331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332static int out_set_callback(struct audio_stream_out *stream,
2333 stream_callback_t callback, void *cookie)
2334{
2335 struct stream_out *out = (struct stream_out *)stream;
2336
2337 ALOGV("%s", __func__);
2338 pthread_mutex_lock(&out->lock);
2339 out->offload_callback = callback;
2340 out->offload_cookie = cookie;
2341 pthread_mutex_unlock(&out->lock);
2342 return 0;
2343}
2344
2345static int out_pause(struct audio_stream_out* stream)
2346{
2347 struct stream_out *out = (struct stream_out *)stream;
2348 int status = -ENOSYS;
2349 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002350 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002351 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 pthread_mutex_lock(&out->lock);
2353 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302354 struct audio_device *adev = out->dev;
2355 int snd_scard_state = get_snd_card_state(adev);
2356
2357 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2358 status = compress_pause(out->compr);
2359
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002361
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302362 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002363 audio_extn_dts_notify_playback_state(out->usecase, 0,
2364 out->sample_rate, popcount(out->channel_mask),
2365 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 }
2367 pthread_mutex_unlock(&out->lock);
2368 }
2369 return status;
2370}
2371
2372static int out_resume(struct audio_stream_out* stream)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375 int status = -ENOSYS;
2376 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002377 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002378 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 status = 0;
2380 pthread_mutex_lock(&out->lock);
2381 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302382 struct audio_device *adev = out->dev;
2383 int snd_scard_state = get_snd_card_state(adev);
2384
2385 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2386 status = compress_resume(out->compr);
2387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002389
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302390 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002391 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2392 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 }
2394 pthread_mutex_unlock(&out->lock);
2395 }
2396 return status;
2397}
2398
2399static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2400{
2401 struct stream_out *out = (struct stream_out *)stream;
2402 int status = -ENOSYS;
2403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002404 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 pthread_mutex_lock(&out->lock);
2406 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2407 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2408 else
2409 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2410 pthread_mutex_unlock(&out->lock);
2411 }
2412 return status;
2413}
2414
2415static int out_flush(struct audio_stream_out* stream)
2416{
2417 struct stream_out *out = (struct stream_out *)stream;
2418 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002419 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002420 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421 pthread_mutex_lock(&out->lock);
2422 stop_compressed_output_l(out);
2423 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002424 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 return 0;
2426 }
2427 return -ENOSYS;
2428}
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430/** audio_stream_in implementation **/
2431static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2432{
2433 struct stream_in *in = (struct stream_in *)stream;
2434
2435 return in->config.rate;
2436}
2437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002438static int in_set_sample_rate(struct audio_stream *stream __unused,
2439 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440{
2441 return -ENOSYS;
2442}
2443
2444static size_t in_get_buffer_size(const struct audio_stream *stream)
2445{
2446 struct stream_in *in = (struct stream_in *)stream;
2447
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002448 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2449 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002450 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2451 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002452
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002453 return in->config.period_size *
2454 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
2457static uint32_t in_get_channels(const struct audio_stream *stream)
2458{
2459 struct stream_in *in = (struct stream_in *)stream;
2460
2461 return in->channel_mask;
2462}
2463
2464static audio_format_t in_get_format(const struct audio_stream *stream)
2465{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002466 struct stream_in *in = (struct stream_in *)stream;
2467
2468 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469}
2470
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002471static int in_set_format(struct audio_stream *stream __unused,
2472 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473{
2474 return -ENOSYS;
2475}
2476
2477static int in_standby(struct audio_stream *stream)
2478{
2479 struct stream_in *in = (struct stream_in *)stream;
2480 struct audio_device *adev = in->dev;
2481 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302482 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2483 stream, in->usecase, use_case_table[in->usecase]);
2484
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002485 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2486 /* Ignore standby in case of voip call because the voip input
2487 * stream is closed in adev_close_input_stream()
2488 */
2489 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2490 return status;
2491 }
2492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002494 if (!in->standby && in->is_st_session) {
2495 ALOGD("%s: sound trigger pcm stop lab", __func__);
2496 audio_extn_sound_trigger_stop_lab(in);
2497 in->standby = 1;
2498 }
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002501 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002503 if (in->pcm) {
2504 pcm_close(in->pcm);
2505 in->pcm = NULL;
2506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002508 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 }
2510 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002511 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 return status;
2513}
2514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002515static int in_dump(const struct audio_stream *stream __unused,
2516 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517{
2518 return 0;
2519}
2520
2521static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2522{
2523 struct stream_in *in = (struct stream_in *)stream;
2524 struct audio_device *adev = in->dev;
2525 struct str_parms *parms;
2526 char *str;
2527 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002528 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302530 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 parms = str_parms_create_str(kvpairs);
2532
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302533 if (!parms)
2534 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002536 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002537
2538 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2539 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 val = atoi(value);
2541 /* no audio source uses val == 0 */
2542 if ((in->source != val) && (val != 0)) {
2543 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002544 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2545 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2546 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2547 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002548 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002549 err = voice_extn_compress_voip_open_input_stream(in);
2550 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002551 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002552 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002553 }
2554 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
2556 }
2557
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002558 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2559 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002561 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 in->device = val;
2563 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002564 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002565 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
2567 }
2568
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002569done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002571 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572
2573 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302574error:
Eric Laurent994a6932013-07-17 11:51:42 -07002575 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 return ret;
2577}
2578
2579static char* in_get_parameters(const struct audio_stream *stream,
2580 const char *keys)
2581{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002582 struct stream_in *in = (struct stream_in *)stream;
2583 struct str_parms *query = str_parms_create_str(keys);
2584 char *str;
2585 char value[256];
2586 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002587
2588 if (!query || !reply) {
2589 ALOGE("in_get_parameters: failed to create query or reply");
2590 return NULL;
2591 }
2592
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 ALOGV("%s: enter: keys - %s", __func__, keys);
2594
2595 voice_extn_in_get_parameters(in, query, reply);
2596
2597 str = str_parms_to_str(reply);
2598 str_parms_destroy(query);
2599 str_parms_destroy(reply);
2600
2601 ALOGV("%s: exit: returns - %s", __func__, str);
2602 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603}
2604
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002605static int in_set_gain(struct audio_stream_in *stream __unused,
2606 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607{
2608 return 0;
2609}
2610
2611static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2612 size_t bytes)
2613{
2614 struct stream_in *in = (struct stream_in *)stream;
2615 struct audio_device *adev = in->dev;
2616 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302617 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302620
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002621 if (in->is_st_session) {
2622 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2623 /* Read from sound trigger HAL */
2624 audio_extn_sound_trigger_read(in, buffer, bytes);
2625 pthread_mutex_unlock(&in->lock);
2626 return bytes;
2627 }
2628
2629 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2630 ALOGD(" %s: sound card is not active/SSR state", __func__);
2631 ret= -EIO;;
2632 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 }
2634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002636 pthread_mutex_lock(&adev->lock);
2637 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2638 ret = voice_extn_compress_voip_start_input_stream(in);
2639 else
2640 ret = start_input_stream(in);
2641 pthread_mutex_unlock(&adev->lock);
2642 if (ret != 0) {
2643 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 }
2645 in->standby = 0;
2646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647
2648 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002649 if (audio_extn_ssr_get_enabled() &&
2650 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002651 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002652 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2653 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002654 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2655 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002656 else
2657 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302658 if (ret < 0)
2659 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 }
2661
2662 /*
2663 * Instead of writing zeroes here, we could trust the hardware
2664 * to always provide zeroes when muted.
2665 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302666 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2667 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 memset(buffer, 0, bytes);
2669
2670exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302671 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302672 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002673 if (-ENETRESET == ret)
2674 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 pthread_mutex_unlock(&in->lock);
2677
2678 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302679 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302680 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302681 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302682 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302683 in->standby = true;
2684 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302685 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002687 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002688 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302689 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
2691 return bytes;
2692}
2693
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002694static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695{
2696 return 0;
2697}
2698
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002699static int add_remove_audio_effect(const struct audio_stream *stream,
2700 effect_handle_t effect,
2701 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002703 struct stream_in *in = (struct stream_in *)stream;
2704 int status = 0;
2705 effect_descriptor_t desc;
2706
2707 status = (*effect)->get_descriptor(effect, &desc);
2708 if (status != 0)
2709 return status;
2710
2711 pthread_mutex_lock(&in->lock);
2712 pthread_mutex_lock(&in->dev->lock);
2713 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2714 in->enable_aec != enable &&
2715 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2716 in->enable_aec = enable;
2717 if (!in->standby)
2718 select_devices(in->dev, in->usecase);
2719 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002720 if (in->enable_ns != enable &&
2721 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2722 in->enable_ns = enable;
2723 if (!in->standby)
2724 select_devices(in->dev, in->usecase);
2725 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002726 pthread_mutex_unlock(&in->dev->lock);
2727 pthread_mutex_unlock(&in->lock);
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 return 0;
2730}
2731
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002732static int in_add_audio_effect(const struct audio_stream *stream,
2733 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
Eric Laurent994a6932013-07-17 11:51:42 -07002735 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002736 return add_remove_audio_effect(stream, effect, true);
2737}
2738
2739static int in_remove_audio_effect(const struct audio_stream *stream,
2740 effect_handle_t effect)
2741{
Eric Laurent994a6932013-07-17 11:51:42 -07002742 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002743 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744}
2745
2746static int adev_open_output_stream(struct audio_hw_device *dev,
2747 audio_io_handle_t handle,
2748 audio_devices_t devices,
2749 audio_output_flags_t flags,
2750 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002751 struct audio_stream_out **stream_out,
2752 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753{
2754 struct audio_device *adev = (struct audio_device *)dev;
2755 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002756 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002757 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302760
2761 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2762 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2763 ALOGE(" sound card is not active rejecting compress output open request");
2764 return -EINVAL;
2765 }
2766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2768
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302769 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2770 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2771 devices, flags, &out->stream);
2772
2773
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002774 if (!out) {
2775 return -ENOMEM;
2776 }
2777
Haynes Mathew George204045b2015-02-25 20:32:03 -08002778 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2779 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 if (devices == AUDIO_DEVICE_NONE)
2782 devices = AUDIO_DEVICE_OUT_SPEAKER;
2783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 out->flags = flags;
2785 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002786 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002787 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002788 out->sample_rate = config->sample_rate;
2789 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2790 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002791 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002792 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002793 out->non_blocking = 0;
2794 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002796 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2797 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002798 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2799 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2800
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002801 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002802 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2803 ret = read_hdmi_channel_masks(out);
2804
2805 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2806 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002807 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002808 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002809 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002810
2811 if (config->sample_rate == 0)
2812 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2813 if (config->channel_mask == 0)
2814 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2815
2816 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2819 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002821 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002823 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2824 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002825 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002826 ret = voice_extn_compress_voip_open_output_stream(out);
2827 if (ret != 0) {
2828 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2829 __func__, ret);
2830 goto error_open;
2831 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2833 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2834 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2835 ALOGE("%s: Unsupported Offload information", __func__);
2836 ret = -EINVAL;
2837 goto error_open;
2838 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002839
2840 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2841 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2842 ALOGV("read and update_pass through formats");
2843 ret = audio_extn_dolby_update_passt_formats(adev, out);
2844 if(ret != 0) {
2845 goto error_open;
2846 }
2847 if(config->offload_info.format == 0)
2848 config->offload_info.format = out->supported_formats[0];
2849 }
2850
Mingming Yin90310102013-11-13 16:57:00 -08002851 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002852 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 ALOGE("%s: Unsupported audio format", __func__);
2854 ret = -EINVAL;
2855 goto error_open;
2856 }
2857
2858 out->compr_config.codec = (struct snd_codec *)
2859 calloc(1, sizeof(struct snd_codec));
2860
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002861 if (!out->compr_config.codec) {
2862 ret = -ENOMEM;
2863 goto error_open;
2864 }
2865
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002866 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867 if (config->offload_info.channel_mask)
2868 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002869 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002871 config->offload_info.channel_mask = config->channel_mask;
2872 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002873 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 out->sample_rate = config->offload_info.sample_rate;
2875
2876 out->stream.set_callback = out_set_callback;
2877 out->stream.pause = out_pause;
2878 out->stream.resume = out_resume;
2879 out->stream.drain = out_drain;
2880 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002881 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002883 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002884 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002885 audio_extn_dolby_get_snd_codec_id(adev, out,
2886 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002887 else
2888 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002890 if (audio_is_offload_pcm(config->offload_info.format)) {
2891 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002892 platform_get_pcm_offload_buffer_size(&config->offload_info);
2893 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2894 out->compr_config.fragment_size =
2895 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002896 } else {
2897 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002898 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2901 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002902 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 out->compr_config.codec->bit_rate =
2904 config->offload_info.bit_rate;
2905 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002906 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002909 /*TODO: Do we need to change it for passthrough */
2910 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911
Mingming Yin3ee55c62014-08-04 14:23:35 -07002912 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2913 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002914 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2915 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002916 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002917 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2918
Mingming Yin3ee55c62014-08-04 14:23:35 -07002919 if (out->bit_width == 24) {
2920 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2921 }
2922
Amit Shekhar6f461b12014-08-01 14:52:58 -07002923 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002924 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002925
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2927 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002928
Alexy Josephaa54c872014-12-03 02:46:47 -08002929 if (config->offload_info.use_small_bufs) {
2930 //this flag is set from framework only if its for PCM formats
2931 //no need to check for PCM format again
2932 out->non_blocking = 0;
2933 out->use_small_bufs = true;
2934 ALOGI("Keep write blocking for small buff: non_blockling %d",
2935 out->non_blocking);
2936 }
2937
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002938 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302939 out->send_next_track_params = false;
2940 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002941 out->offload_state = OFFLOAD_STATE_IDLE;
2942 out->playback_started = 0;
2943
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002944 audio_extn_dts_create_state_notifier_node(out->usecase);
2945
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946 create_offload_callback_thread(out);
2947 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2948 __func__, config->offload_info.version,
2949 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002950 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002951 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002952 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2953 ret = voice_check_and_set_incall_music_usecase(adev, out);
2954 if (ret != 0) {
2955 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2956 __func__, ret);
2957 goto error_open;
2958 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002959 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2960 if (config->sample_rate == 0)
2961 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2962 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2963 config->sample_rate != 8000) {
2964 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2965 ret = -EINVAL;
2966 goto error_open;
2967 }
2968 out->sample_rate = config->sample_rate;
2969 out->config.rate = config->sample_rate;
2970 if (config->format == AUDIO_FORMAT_DEFAULT)
2971 config->format = AUDIO_FORMAT_PCM_16_BIT;
2972 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2973 config->format = AUDIO_FORMAT_PCM_16_BIT;
2974 ret = -EINVAL;
2975 goto error_open;
2976 }
2977 out->format = config->format;
2978 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2979 out->config = pcm_config_afe_proxy_playback;
2980 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002981 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002982 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2984 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002985 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002986 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2987 format = AUDIO_FORMAT_PCM_16_BIT;
2988 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2989 out->config = pcm_config_deep_buffer;
2990 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002991 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002992 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002993 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002994 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002995 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002996 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 }
2998
Amit Shekhar1d896042014-10-03 13:16:09 -07002999 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3000 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003001 /* TODO remove this hardcoding and check why width is zero*/
3002 if (out->bit_width == 0)
3003 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003004 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3005 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003006 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303007 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003008 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3009 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3010 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003011 if(adev->primary_output == NULL)
3012 adev->primary_output = out;
3013 else {
3014 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003015 ret = -EEXIST;
3016 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003017 }
3018 }
3019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 /* Check if this usecase is already existing */
3021 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003022 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3023 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003026 ret = -EEXIST;
3027 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 }
3029 pthread_mutex_unlock(&adev->lock);
3030
3031 out->stream.common.get_sample_rate = out_get_sample_rate;
3032 out->stream.common.set_sample_rate = out_set_sample_rate;
3033 out->stream.common.get_buffer_size = out_get_buffer_size;
3034 out->stream.common.get_channels = out_get_channels;
3035 out->stream.common.get_format = out_get_format;
3036 out->stream.common.set_format = out_set_format;
3037 out->stream.common.standby = out_standby;
3038 out->stream.common.dump = out_dump;
3039 out->stream.common.set_parameters = out_set_parameters;
3040 out->stream.common.get_parameters = out_get_parameters;
3041 out->stream.common.add_audio_effect = out_add_audio_effect;
3042 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3043 out->stream.get_latency = out_get_latency;
3044 out->stream.set_volume = out_set_volume;
3045 out->stream.write = out_write;
3046 out->stream.get_render_position = out_get_render_position;
3047 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003048 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003051 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003052 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053
3054 config->format = out->stream.common.get_format(&out->stream.common);
3055 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3056 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3057
3058 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303059 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3060 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003061
3062 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3063 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3064 popcount(out->channel_mask), out->playback_started);
3065
Eric Laurent994a6932013-07-17 11:51:42 -07003066 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003068
3069error_open:
3070 free(out);
3071 *stream_out = NULL;
3072 ALOGD("%s: exit: ret %d", __func__, ret);
3073 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074}
3075
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003076static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 struct audio_stream_out *stream)
3078{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 struct stream_out *out = (struct stream_out *)stream;
3080 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003082
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303083 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3084
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003085 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303086 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303088 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003089 if(ret != 0)
3090 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3091 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003092 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003093 out_standby(&stream->common);
3094
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003095 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003096 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003098 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 if (out->compr_config.codec != NULL)
3100 free(out->compr_config.codec);
3101 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003102
3103 if (adev->voice_tx_output == out)
3104 adev->voice_tx_output = NULL;
3105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 pthread_cond_destroy(&out->cond);
3107 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003109 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110}
3111
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112static void close_compress_sessions(struct audio_device *adev)
3113{
Mingming Yin7b762e72015-03-04 13:47:32 -08003114 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303115 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003116 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003117 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303118
3119 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003120 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303121 if (is_offload_usecase(usecase->id)) {
3122 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003123 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3124 out = usecase->stream.out;
3125 pthread_mutex_unlock(&adev->lock);
3126 out_standby(&out->stream.common);
3127 pthread_mutex_lock(&adev->lock);
3128 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303129 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 }
3131 pthread_mutex_unlock(&adev->lock);
3132}
3133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3135{
3136 struct audio_device *adev = (struct audio_device *)dev;
3137 struct str_parms *parms;
3138 char *str;
3139 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003140 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003141 int ret;
3142 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003144 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303147 if (!parms)
3148 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003149 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3150 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303152 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303153 struct listnode *node;
3154 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303155 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303156 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003157 //close compress sessions on OFFLINE status
3158 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303159 } else if (strstr(snd_card_status, "ONLINE")) {
3160 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303161 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303162 if (!platform_is_acdb_initialized(adev->platform)) {
3163 ret = platform_acdb_init(adev->platform);
3164 if(ret)
3165 ALOGE("acdb initialization is failed");
3166
3167 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303168 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303169 }
3170
3171 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003172 status = voice_set_parameters(adev, parms);
3173 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003174 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003176 status = platform_set_parameters(adev->platform, parms);
3177 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003178 goto done;
3179
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3181 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003182 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3184 adev->bluetooth_nrec = true;
3185 else
3186 adev->bluetooth_nrec = false;
3187 }
3188
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003189 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3190 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3192 adev->screen_off = false;
3193 else
3194 adev->screen_off = true;
3195 }
3196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 ret = str_parms_get_int(parms, "rotation", &val);
3198 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003199 bool reverse_speakers = false;
3200 switch(val) {
3201 // FIXME: note that the code below assumes that the speakers are in the correct placement
3202 // relative to the user when the device is rotated 90deg from its default rotation. This
3203 // assumption is device-specific, not platform-specific like this code.
3204 case 270:
3205 reverse_speakers = true;
3206 break;
3207 case 0:
3208 case 90:
3209 case 180:
3210 break;
3211 default:
3212 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003213 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003214 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003215 if (status == 0) {
3216 if (adev->speaker_lr_swap != reverse_speakers) {
3217 adev->speaker_lr_swap = reverse_speakers;
3218 // only update the selected device if there is active pcm playback
3219 struct audio_usecase *usecase;
3220 struct listnode *node;
3221 list_for_each(node, &adev->usecase_list) {
3222 usecase = node_to_item(node, struct audio_usecase, list);
3223 if (usecase->type == PCM_PLAYBACK) {
3224 select_devices(adev, usecase->id);
3225 break;
3226 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003227 }
3228 }
3229 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003230 }
3231
Mingming Yin514a8bc2014-07-29 15:22:21 -07003232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3233 if (ret >= 0) {
3234 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3235 adev->bt_wb_speech_enabled = true;
3236 else
3237 adev->bt_wb_speech_enabled = false;
3238 }
3239
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003240 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3241 if (ret >= 0) {
3242 val = atoi(value);
3243 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3244 ALOGV("cache new edid");
3245 platform_cache_edid(adev->platform);
3246 }
3247 }
3248
3249 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3250 if (ret >= 0) {
3251 val = atoi(value);
3252 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3253 ALOGV("invalidate cached edid");
3254 platform_invalidate_edid(adev->platform);
3255 }
3256 }
3257
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003258 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003259
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003260done:
3261 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003262 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303263error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003264 ALOGV("%s: exit with code(%d)", __func__, status);
3265 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266}
3267
3268static char* adev_get_parameters(const struct audio_hw_device *dev,
3269 const char *keys)
3270{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003271 struct audio_device *adev = (struct audio_device *)dev;
3272 struct str_parms *reply = str_parms_create();
3273 struct str_parms *query = str_parms_create_str(keys);
3274 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303275 char value[256] = {0};
3276 int ret = 0;
3277
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003278 if (!query || !reply) {
3279 ALOGE("adev_get_parameters: failed to create query or reply");
3280 return NULL;
3281 }
3282
Naresh Tannirud7205b62014-06-20 02:54:48 +05303283 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3284 sizeof(value));
3285 if (ret >=0) {
3286 int val = 1;
3287 pthread_mutex_lock(&adev->snd_card_status.lock);
3288 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3289 val = 0;
3290 pthread_mutex_unlock(&adev->snd_card_status.lock);
3291 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3292 goto exit;
3293 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003294
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003295 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003296 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003297 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003298 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303299 pthread_mutex_unlock(&adev->lock);
3300
Naresh Tannirud7205b62014-06-20 02:54:48 +05303301exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003302 str = str_parms_to_str(reply);
3303 str_parms_destroy(query);
3304 str_parms_destroy(reply);
3305
3306 ALOGV("%s: exit: returns - %s", __func__, str);
3307 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308}
3309
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003310static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311{
3312 return 0;
3313}
3314
3315static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3316{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003317 int ret;
3318 struct audio_device *adev = (struct audio_device *)dev;
3319 pthread_mutex_lock(&adev->lock);
3320 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003321 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003322 pthread_mutex_unlock(&adev->lock);
3323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3327 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3333 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return -ENOSYS;
3336}
3337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003338static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3339 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340{
3341 return -ENOSYS;
3342}
3343
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003344static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3345 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346{
3347 return -ENOSYS;
3348}
3349
3350static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3351{
3352 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 pthread_mutex_lock(&adev->lock);
3355 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003356 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3359 voice_is_in_call(adev)) {
3360 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303361 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362 adev->current_call_output = NULL;
3363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 }
3365 pthread_mutex_unlock(&adev->lock);
3366 return 0;
3367}
3368
3369static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3370{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003371 int ret;
3372
3373 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003374 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003375 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3376 pthread_mutex_unlock(&adev->lock);
3377
3378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379}
3380
3381static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3382{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003383 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 return 0;
3385}
3386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003387static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 const struct audio_config *config)
3389{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003390 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003392 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3393 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394}
3395
3396static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003397 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 audio_devices_t devices,
3399 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003400 struct audio_stream_in **stream_in,
3401 audio_input_flags_t flags __unused,
3402 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003403 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404{
3405 struct audio_device *adev = (struct audio_device *)dev;
3406 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003407 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003408 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003409 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 *stream_in = NULL;
3412 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3413 return -EINVAL;
3414
3415 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003416
3417 if (!in) {
3418 ALOGE("failed to allocate input stream");
3419 return -ENOMEM;
3420 }
3421
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303422 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003423 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3424 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003426 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->stream.common.get_sample_rate = in_get_sample_rate;
3429 in->stream.common.set_sample_rate = in_set_sample_rate;
3430 in->stream.common.get_buffer_size = in_get_buffer_size;
3431 in->stream.common.get_channels = in_get_channels;
3432 in->stream.common.get_format = in_get_format;
3433 in->stream.common.set_format = in_set_format;
3434 in->stream.common.standby = in_standby;
3435 in->stream.common.dump = in_dump;
3436 in->stream.common.set_parameters = in_set_parameters;
3437 in->stream.common.get_parameters = in_get_parameters;
3438 in->stream.common.add_audio_effect = in_add_audio_effect;
3439 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3440 in->stream.set_gain = in_set_gain;
3441 in->stream.read = in_read;
3442 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3443
3444 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003445 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 in->standby = 1;
3448 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003449 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450
3451 /* Update config params with the requested sample rate and channels */
3452 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003453 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3454 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3455 is_low_latency = true;
3456#if LOW_LATENCY_CAPTURE_USE_CASE
3457 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3458#endif
3459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003462 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003464 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303465 if (adev->mode != AUDIO_MODE_IN_CALL) {
3466 ret = -EINVAL;
3467 goto err_open;
3468 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003469 if (config->sample_rate == 0)
3470 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3471 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3472 config->sample_rate != 8000) {
3473 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477 if (config->format == AUDIO_FORMAT_DEFAULT)
3478 config->format = AUDIO_FORMAT_PCM_16_BIT;
3479 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3480 config->format = AUDIO_FORMAT_PCM_16_BIT;
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
3484
3485 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3486 in->config = pcm_config_afe_proxy_record;
3487 in->config.channels = channel_count;
3488 in->config.rate = config->sample_rate;
3489 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003490 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003492 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3493 ret = -EINVAL;
3494 goto err_open;
3495 }
3496 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003497 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003498 }
Mingming Yine62d7842013-10-25 16:26:03 -07003499 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003500 audio_extn_compr_cap_format_supported(config->format) &&
3501 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003503 } else {
3504 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003505 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003506 buffer_size = get_input_buffer_size(config->sample_rate,
3507 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003508 channel_count,
3509 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003510 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003511 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3512 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3513 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3514 (in->config.rate == 8000 || in->config.rate == 16000) &&
3515 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3516 voice_extn_compress_voip_open_input_stream(in);
3517 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003520 /* This stream could be for sound trigger lab,
3521 get sound trigger pcm if present */
3522 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303523 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003526 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003527 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
3529err_open:
3530 free(in);
3531 *stream_in = NULL;
3532 return ret;
3533}
3534
3535static void adev_close_input_stream(struct audio_hw_device *dev,
3536 struct audio_stream_in *stream)
3537{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003538 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003539 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003540 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303541
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303542 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003543
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303544 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi50650f42015-07-06 15:07:14 -07003545 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303546
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003547 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303548 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303550 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003551 if (ret != 0)
3552 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3553 __func__, ret);
3554 } else
3555 in_standby(&stream->common);
3556
Mingming Yin7b762e72015-03-04 13:47:32 -08003557 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003558 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003559 audio_extn_ssr_deinit();
3560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561
Mingming Yine62d7842013-10-25 16:26:03 -07003562 if(audio_extn_compr_cap_enabled() &&
3563 audio_extn_compr_cap_format_supported(in->config.format))
3564 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003565
3566 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 return;
3568}
3569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003570static int adev_dump(const audio_hw_device_t *device __unused,
3571 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572{
3573 return 0;
3574}
3575
3576static int adev_close(hw_device_t *device)
3577{
3578 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003579
3580 if (!adev)
3581 return 0;
3582
3583 pthread_mutex_lock(&adev_init_lock);
3584
3585 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003586 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003587 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003588 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003589 audio_route_free(adev->audio_route);
3590 free(adev->snd_dev_ref_cnt);
3591 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003592 free(device);
3593 adev = NULL;
3594 }
3595 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 return 0;
3597}
3598
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003599/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3600 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3601 * just that it _might_ work.
3602 */
3603static int period_size_is_plausible_for_low_latency(int period_size)
3604{
3605 switch (period_size) {
3606 case 160:
3607 case 240:
3608 case 320:
3609 case 480:
3610 return 1;
3611 default:
3612 return 0;
3613 }
3614}
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616static int adev_open(const hw_module_t *module, const char *name,
3617 hw_device_t **device)
3618{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003619 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003621 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3623
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003624 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003625 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003626 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003627 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003628 ALOGD("%s: returning existing instance of adev", __func__);
3629 ALOGD("%s: exit", __func__);
3630 pthread_mutex_unlock(&adev_init_lock);
3631 return 0;
3632 }
3633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 adev = calloc(1, sizeof(struct audio_device));
3635
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003636 if (!adev) {
3637 pthread_mutex_unlock(&adev_init_lock);
3638 return -ENOMEM;
3639 }
3640
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003641 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3644 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3645 adev->device.common.module = (struct hw_module_t *)module;
3646 adev->device.common.close = adev_close;
3647
3648 adev->device.init_check = adev_init_check;
3649 adev->device.set_voice_volume = adev_set_voice_volume;
3650 adev->device.set_master_volume = adev_set_master_volume;
3651 adev->device.get_master_volume = adev_get_master_volume;
3652 adev->device.set_master_mute = adev_set_master_mute;
3653 adev->device.get_master_mute = adev_get_master_mute;
3654 adev->device.set_mode = adev_set_mode;
3655 adev->device.set_mic_mute = adev_set_mic_mute;
3656 adev->device.get_mic_mute = adev_get_mic_mute;
3657 adev->device.set_parameters = adev_set_parameters;
3658 adev->device.get_parameters = adev_get_parameters;
3659 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3660 adev->device.open_output_stream = adev_open_output_stream;
3661 adev->device.close_output_stream = adev_close_output_stream;
3662 adev->device.open_input_stream = adev_open_input_stream;
3663 adev->device.close_input_stream = adev_close_input_stream;
3664 adev->device.dump = adev_dump;
3665
3666 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003668 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003669 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003672 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003673 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003674 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003675 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003676 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003677 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003678 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303679 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303680
3681 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3682 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003684 adev->platform = platform_init(adev);
3685 if (!adev->platform) {
3686 free(adev->snd_dev_ref_cnt);
3687 free(adev);
3688 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3689 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003690 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003691 return -EINVAL;
3692 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003693
Naresh Tanniru4c630392014-05-12 01:05:52 +05303694 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3695
Eric Laurentc4aef752013-09-12 17:45:53 -07003696 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3697 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3698 if (adev->visualizer_lib == NULL) {
3699 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3700 } else {
3701 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3702 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003703 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003704 "visualizer_hal_start_output");
3705 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003706 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003707 "visualizer_hal_stop_output");
3708 }
3709 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003710 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003711 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003712
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003713 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3714 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3715 if (adev->offload_effects_lib == NULL) {
3716 ALOGE("%s: DLOPEN failed for %s", __func__,
3717 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3718 } else {
3719 ALOGV("%s: DLOPEN successful for %s", __func__,
3720 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3721 adev->offload_effects_start_output =
3722 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3723 "offload_effects_bundle_hal_start_output");
3724 adev->offload_effects_stop_output =
3725 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3726 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003727 adev->offload_effects_set_hpx_state =
3728 (int (*)(bool))dlsym(adev->offload_effects_lib,
3729 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003730 }
3731 }
3732
Mingming Yin514a8bc2014-07-29 15:22:21 -07003733 adev->bt_wb_speech_enabled = false;
3734
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003735 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 *device = &adev->device.common;
3737
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003738 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3739 &adev->streams_output_cfg_list);
3740
Kiran Kandi910e1862013-10-29 13:29:42 -07003741 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003742
3743 char value[PROPERTY_VALUE_MAX];
3744 int trial;
3745 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3746 trial = atoi(value);
3747 if (period_size_is_plausible_for_low_latency(trial)) {
3748 pcm_config_low_latency.period_size = trial;
3749 pcm_config_low_latency.start_threshold = trial / 4;
3750 pcm_config_low_latency.avail_min = trial / 4;
3751 configured_low_latency_capture_period_size = trial;
3752 }
3753 }
3754 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3755 trial = atoi(value);
3756 if (period_size_is_plausible_for_low_latency(trial)) {
3757 configured_low_latency_capture_period_size = trial;
3758 }
3759 }
3760
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003761 pthread_mutex_unlock(&adev_init_lock);
3762
Eric Laurent994a6932013-07-17 11:51:42 -07003763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 return 0;
3765}
3766
3767static struct hw_module_methods_t hal_module_methods = {
3768 .open = adev_open,
3769};
3770
3771struct audio_module HAL_MODULE_INFO_SYM = {
3772 .common = {
3773 .tag = HARDWARE_MODULE_TAG,
3774 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3775 .hal_api_version = HARDWARE_HAL_API_VERSION,
3776 .id = AUDIO_HARDWARE_MODULE_ID,
3777 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003778 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 .methods = &hal_module_methods,
3780 },
3781};