blob: e2db95b6904591f2efc8703165553c9df7c8347e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Linux Build Service Account75e43952015-08-26 19:58:56 -0700572 if (snd_device == SND_DEVICE_OUT_HDMI)
573 adev->mChannelStatusSet = false;
574
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200575 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700576 audio_extn_sound_trigger_update_device_status(snd_device,
577 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530578 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800579 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 return 0;
583}
584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585static void check_usecases_codec_backend(struct audio_device *adev,
586 struct audio_usecase *uc_info,
587 snd_device_t snd_device)
588{
589 struct listnode *node;
590 struct audio_usecase *usecase;
591 bool switch_device[AUDIO_USECASE_MAX];
592 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530593 int backend_idx = DEFAULT_CODEC_BACKEND;
594 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595
596 /*
597 * This function is to make sure that all the usecases that are active on
598 * the hardware codec backend are always routed to any one device that is
599 * handled by the hardware codec.
600 * For example, if low-latency and deep-buffer usecases are currently active
601 * on speaker and out_set_parameters(headset) is received on low-latency
602 * output, then we have to make sure deep-buffer is also switched to headset,
603 * because of the limitation that both the devices cannot be enabled
604 * at the same time as they share the same backend.
605 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700606 /*
607 * This call is to check if we need to force routing for a particular stream
608 * If there is a backend configuration change for the device when a
609 * new stream starts, then ADM needs to be closed and re-opened with the new
610 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530611 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700612 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530613 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
614 snd_device);
615 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800617 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800618 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 for (i = 0; i < AUDIO_USECASE_MAX; i++)
620 switch_device[i] = false;
621
622 list_for_each(node, &adev->usecase_list) {
623 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530624
625 if (usecase == uc_info)
626 continue;
627 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
628 ALOGV("%s: backend_idx: %d,"
629 "usecase_backend_idx: %d, curr device: %s, usecase device:"
630 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530631 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800633 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700634 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
636 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530637 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530638 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700639 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700640 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641 switch_device[usecase->id] = true;
642 num_uc_to_switch++;
643 }
644 }
645
646 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700647 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530649 /* Make sure the previous devices to be disabled first and then enable the
650 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
653 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700654 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 }
656 }
657
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700662 }
663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 /* Re-route all the usecases on the shared backend other than the
666 specified usecase to new snd devices */
667 list_for_each(node, &adev->usecase_list) {
668 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530669 /* Update the out_snd_device only before enabling the audio route */
670 if (switch_device[usecase->id] ) {
671 usecase->out_snd_device = snd_device;
672 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530673 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700674 }
675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 }
677}
678
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700679static void check_and_route_capture_usecases(struct audio_device *adev,
680 struct audio_usecase *uc_info,
681 snd_device_t snd_device)
682{
683 struct listnode *node;
684 struct audio_usecase *usecase;
685 bool switch_device[AUDIO_USECASE_MAX];
686 int i, num_uc_to_switch = 0;
687
688 /*
689 * This function is to make sure that all the active capture usecases
690 * are always routed to the same input sound device.
691 * For example, if audio-record and voice-call usecases are currently
692 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
693 * is received for voice call then we have to make sure that audio-record
694 * usecase is also switched to earpiece i.e. voice-dmic-ef,
695 * because of the limitation that two devices cannot be enabled
696 * at the same time if they share the same backend.
697 */
698 for (i = 0; i < AUDIO_USECASE_MAX; i++)
699 switch_device[i] = false;
700
701 list_for_each(node, &adev->usecase_list) {
702 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800703 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700705 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700706 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530707 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
708 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700709 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
711 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700712 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700713 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 switch_device[usecase->id] = true;
715 num_uc_to_switch++;
716 }
717 }
718
719 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700720 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700721
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530722 /* Make sure the previous devices to be disabled first and then enable the
723 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
726 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800728 }
729 }
730
731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
733 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700734 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735 }
736 }
737
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 /* Re-route all the usecases on the shared backend other than the
739 specified usecase to new snd devices */
740 list_for_each(node, &adev->usecase_list) {
741 usecase = node_to_item(node, struct audio_usecase, list);
742 /* Update the in_snd_device only before enabling the audio route */
743 if (switch_device[usecase->id] ) {
744 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800745 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530746 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700747 }
748 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749 }
750}
751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700753static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700755 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700756 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757
758 switch (channels) {
759 /*
760 * Do not handle stereo output in Multi-channel cases
761 * Stereo case is handled in normal playback path
762 */
763 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700764 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770 break;
771 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700772 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
777 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779 break;
780 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700781 ALOGE("HDMI does not support multi channel playback");
782 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 break;
784 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700785 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786}
787
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800788audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
789 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700790{
791 struct audio_usecase *usecase;
792 struct listnode *node;
793
794 list_for_each(node, &adev->usecase_list) {
795 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800796 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700797 ALOGV("%s: usecase id %d", __func__, usecase->id);
798 return usecase->id;
799 }
800 }
801 return USECASE_INVALID;
802}
803
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700804struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700805 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700806{
807 struct audio_usecase *usecase;
808 struct listnode *node;
809
810 list_for_each(node, &adev->usecase_list) {
811 usecase = node_to_item(node, struct audio_usecase, list);
812 if (usecase->id == uc_id)
813 return usecase;
814 }
815 return NULL;
816}
817
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800820 snd_device_t out_snd_device = SND_DEVICE_NONE;
821 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 struct audio_usecase *usecase = NULL;
823 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800824 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800825 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800826 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800827 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 usecase = get_usecase_from_list(adev, uc_id);
831 if (usecase == NULL) {
832 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
833 return -EINVAL;
834 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800836 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800837 (usecase->type == VOIP_CALL) ||
838 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700839 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800840 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700841 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 usecase->devices = usecase->stream.out->devices;
843 } else {
844 /*
845 * If the voice call is active, use the sound devices of voice call usecase
846 * so that it would not result any device switch. All the usecases will
847 * be switched to new device when select_devices() is called for voice call
848 * usecase. This is to avoid switching devices for voice call when
849 * check_usecases_codec_backend() is called below.
850 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700851 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700852 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800853 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700854 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
855 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 in_snd_device = vc_usecase->in_snd_device;
857 out_snd_device = vc_usecase->out_snd_device;
858 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800859 } else if (voice_extn_compress_voip_is_active(adev)) {
860 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700861 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530862 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700863 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800864 in_snd_device = voip_usecase->in_snd_device;
865 out_snd_device = voip_usecase->out_snd_device;
866 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800867 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800868 hfp_ucid = audio_extn_hfp_get_usecase();
869 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700870 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800871 in_snd_device = hfp_usecase->in_snd_device;
872 out_snd_device = hfp_usecase->out_snd_device;
873 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
875 if (usecase->type == PCM_PLAYBACK) {
876 usecase->devices = usecase->stream.out->devices;
877 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700878 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700879 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800880 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 if (usecase->stream.out == adev->primary_output &&
882 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800883 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700884 select_devices(adev, adev->active_input->usecase);
885 }
886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 } else if (usecase->type == PCM_CAPTURE) {
888 usecase->devices = usecase->stream.in->device;
889 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530892 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
893 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
894 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
895 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800897 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700898 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
899 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700901 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
904 }
905
906 if (out_snd_device == usecase->out_snd_device &&
907 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 return 0;
909 }
910
sangwoobc677242013-08-08 16:53:43 +0900911 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700912 out_snd_device, platform_get_snd_device_name(out_snd_device),
913 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915 /*
916 * Limitation: While in call, to do a device switch we need to disable
917 * and enable both RX and TX devices though one of them is same as current
918 * device.
919 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700920 if ((usecase->type == VOICE_CALL) &&
921 (usecase->in_snd_device != SND_DEVICE_NONE) &&
922 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700923 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700924 }
925
926 if (((usecase->type == VOICE_CALL) ||
927 (usecase->type == VOIP_CALL)) &&
928 (usecase->out_snd_device != SND_DEVICE_NONE)) {
929 /* Disable sidetone only if voice/voip call already exists */
930 if (voice_is_call_state_active(adev) ||
931 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700932 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800933 }
934
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 /* Disable current sound devices */
936 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700937 disable_audio_route(adev, usecase);
938 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939 }
940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700942 disable_audio_route(adev, usecase);
943 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 }
945
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800946 /* Applicable only on the targets that has external modem.
947 * New device information should be sent to modem before enabling
948 * the devices to reduce in-call device switch time.
949 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700950 if ((usecase->type == VOICE_CALL) &&
951 (usecase->in_snd_device != SND_DEVICE_NONE) &&
952 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800953 status = platform_switch_voice_call_enable_device_config(adev->platform,
954 out_snd_device,
955 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700956 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800957
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 /* Enable new sound devices */
959 if (out_snd_device != SND_DEVICE_NONE) {
960 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
961 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 }
964
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 if (in_snd_device != SND_DEVICE_NONE) {
966 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969
Avinash Vaish71a8b972014-07-24 15:36:33 +0530970 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700971 status = platform_switch_voice_call_device_post(adev->platform,
972 out_snd_device,
973 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530974 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700975 /* Enable sidetone only if voice/voip call already exists */
976 if (voice_is_call_state_active(adev) ||
977 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700978 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530979 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800980
sangwoo170731f2013-06-08 15:36:36 +0900981 usecase->in_snd_device = in_snd_device;
982 usecase->out_snd_device = out_snd_device;
983
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530984 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700985 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530986 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700987 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530988 usecase->stream.out->flags,
989 usecase->stream.out->format,
990 usecase->stream.out->sample_rate,
991 usecase->stream.out->bit_width,
992 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700993 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530994 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700995
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700996 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900997
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800998 /* Applicable only on the targets that has external modem.
999 * Enable device command should be sent to modem only after
1000 * enabling voice call mixer controls
1001 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001002 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001003 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1004 out_snd_device,
1005 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301006 ALOGD("%s: done",__func__);
1007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008 return status;
1009}
1010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001011static int stop_input_stream(struct stream_in *in)
1012{
1013 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 struct audio_usecase *uc_info;
1015 struct audio_device *adev = in->dev;
1016
Eric Laurentc8400632013-02-14 19:04:54 -08001017 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018
Eric Laurent994a6932013-07-17 11:51:42 -07001019 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 uc_info = get_usecase_from_list(adev, in->usecase);
1022 if (uc_info == NULL) {
1023 ALOGE("%s: Could not find the usecase (%d) in the list",
1024 __func__, in->usecase);
1025 return -EINVAL;
1026 }
1027
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001028 /* Close in-call recording streams */
1029 voice_check_and_stop_incall_rec_usecase(adev, in);
1030
Eric Laurent150dbfe2013-02-27 14:31:02 -08001031 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001032 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033
1034 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001035 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001037 list_remove(&uc_info->list);
1038 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Eric Laurent994a6932013-07-17 11:51:42 -07001040 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 return ret;
1042}
1043
1044int start_input_stream(struct stream_in *in)
1045{
1046 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001047 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 struct audio_usecase *uc_info;
1049 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301050 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301052 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1053 if (get_usecase_from_list(adev, usecase) == NULL)
1054 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301055 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1056 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001057
Naresh Tanniru80659832014-06-04 18:17:56 +05301058
1059 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301060 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301061 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301062 goto error_config;
1063 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301064
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001065 /* Check if source matches incall recording usecase criteria */
1066 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1067 if (ret)
1068 goto error_config;
1069 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301070 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1071
1072 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1073 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1074 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1075 goto error_config;
1076 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001077
Eric Laurentb23d5282013-05-14 15:27:20 -07001078 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079 if (in->pcm_device_id < 0) {
1080 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1081 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001082 ret = -EINVAL;
1083 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085
1086 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001088
1089 if (!uc_info) {
1090 ret = -ENOMEM;
1091 goto error_config;
1092 }
1093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 uc_info->id = in->usecase;
1095 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001096 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 uc_info->devices = in->device;
1098 uc_info->in_snd_device = SND_DEVICE_NONE;
1099 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001101 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301102 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104
Eric Laurentc8400632013-02-14 19:04:54 -08001105 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001106 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1107
1108 unsigned int flags = PCM_IN;
1109 unsigned int pcm_open_retry_count = 0;
1110
1111 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1112 flags |= PCM_MMAP | PCM_NOIRQ;
1113 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1114 }
1115
1116 while (1) {
1117 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1118 flags, &in->config);
1119 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1120 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1121 if (in->pcm != NULL) {
1122 pcm_close(in->pcm);
1123 in->pcm = NULL;
1124 }
1125 if (pcm_open_retry_count-- == 0) {
1126 ret = -EIO;
1127 goto error_open;
1128 }
1129 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1130 continue;
1131 }
1132 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301134 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301135
Eric Laurent994a6932013-07-17 11:51:42 -07001136 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001137 return ret;
1138
1139error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301141 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001142
1143error_config:
1144 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001146
1147 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148}
1149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001150/* must be called with out->lock locked */
1151static int send_offload_cmd_l(struct stream_out* out, int command)
1152{
1153 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1154
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001155 if (!cmd) {
1156 ALOGE("failed to allocate mem for command 0x%x", command);
1157 return -ENOMEM;
1158 }
1159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001160 ALOGVV("%s %d", __func__, command);
1161
1162 cmd->cmd = command;
1163 list_add_tail(&out->offload_cmd_list, &cmd->node);
1164 pthread_cond_signal(&out->offload_cond);
1165 return 0;
1166}
1167
1168/* must be called iwth out->lock locked */
1169static void stop_compressed_output_l(struct stream_out *out)
1170{
1171 out->offload_state = OFFLOAD_STATE_IDLE;
1172 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001173 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001174 if (out->compr != NULL) {
1175 compress_stop(out->compr);
1176 while (out->offload_thread_blocked) {
1177 pthread_cond_wait(&out->cond, &out->lock);
1178 }
1179 }
1180}
1181
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001182bool is_offload_usecase(audio_usecase_t uc_id)
1183{
1184 unsigned int i;
1185 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1186 if (uc_id == offload_usecases[i])
1187 return true;
1188 }
1189 return false;
1190}
1191
1192static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1193{
1194 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1195 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1196 char value[PROPERTY_VALUE_MAX] = {0};
1197
1198 property_get("audio.offload.multiple.enabled", value, NULL);
1199 if (!(atoi(value) || !strncmp("true", value, 4)))
1200 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1201
1202 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1203 for (i = 0; i < num_usecase; i++) {
1204 if (!(adev->offload_usecases_state & (0x1<<i))) {
1205 adev->offload_usecases_state |= 0x1 << i;
1206 ret = offload_usecases[i];
1207 break;
1208 }
1209 }
1210 ALOGV("%s: offload usecase is %d", __func__, ret);
1211 return ret;
1212}
1213
1214static void free_offload_usecase(struct audio_device *adev,
1215 audio_usecase_t uc_id)
1216{
1217 unsigned int i;
1218 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1219 if (offload_usecases[i] == uc_id) {
1220 adev->offload_usecases_state &= ~(0x1<<i);
1221 break;
1222 }
1223 }
1224 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1225}
1226
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001227static void *offload_thread_loop(void *context)
1228{
1229 struct stream_out *out = (struct stream_out *) context;
1230 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001231 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1234 set_sched_policy(0, SP_FOREGROUND);
1235 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1236
1237 ALOGV("%s", __func__);
1238 pthread_mutex_lock(&out->lock);
1239 for (;;) {
1240 struct offload_cmd *cmd = NULL;
1241 stream_callback_event_t event;
1242 bool send_callback = false;
1243
1244 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1245 __func__, list_empty(&out->offload_cmd_list),
1246 out->offload_state);
1247 if (list_empty(&out->offload_cmd_list)) {
1248 ALOGV("%s SLEEPING", __func__);
1249 pthread_cond_wait(&out->offload_cond, &out->lock);
1250 ALOGV("%s RUNNING", __func__);
1251 continue;
1252 }
1253
1254 item = list_head(&out->offload_cmd_list);
1255 cmd = node_to_item(item, struct offload_cmd, node);
1256 list_remove(item);
1257
1258 ALOGVV("%s STATE %d CMD %d out->compr %p",
1259 __func__, out->offload_state, cmd->cmd, out->compr);
1260
1261 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1262 free(cmd);
1263 break;
1264 }
1265
1266 if (out->compr == NULL) {
1267 ALOGE("%s: Compress handle is NULL", __func__);
1268 pthread_cond_signal(&out->cond);
1269 continue;
1270 }
1271 out->offload_thread_blocked = true;
1272 pthread_mutex_unlock(&out->lock);
1273 send_callback = false;
1274 switch(cmd->cmd) {
1275 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001276 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001278 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001279 send_callback = true;
1280 event = STREAM_CBK_EVENT_WRITE_READY;
1281 break;
1282 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001283 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301284 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301286 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001287 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301288 if (ret < 0)
1289 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301290 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301291 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001292 compress_drain(out->compr);
1293 else
1294 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301295 if (ret != -ENETRESET) {
1296 send_callback = true;
1297 event = STREAM_CBK_EVENT_DRAIN_READY;
1298 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1299 } else
1300 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 break;
1302 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001303 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001305 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 send_callback = true;
1307 event = STREAM_CBK_EVENT_DRAIN_READY;
1308 break;
1309 default:
1310 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1311 break;
1312 }
1313 pthread_mutex_lock(&out->lock);
1314 out->offload_thread_blocked = false;
1315 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001316 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001317 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001319 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 free(cmd);
1321 }
1322
1323 pthread_cond_signal(&out->cond);
1324 while (!list_empty(&out->offload_cmd_list)) {
1325 item = list_head(&out->offload_cmd_list);
1326 list_remove(item);
1327 free(node_to_item(item, struct offload_cmd, node));
1328 }
1329 pthread_mutex_unlock(&out->lock);
1330
1331 return NULL;
1332}
1333
1334static int create_offload_callback_thread(struct stream_out *out)
1335{
1336 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1337 list_init(&out->offload_cmd_list);
1338 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1339 offload_thread_loop, out);
1340 return 0;
1341}
1342
1343static int destroy_offload_callback_thread(struct stream_out *out)
1344{
1345 pthread_mutex_lock(&out->lock);
1346 stop_compressed_output_l(out);
1347 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1348
1349 pthread_mutex_unlock(&out->lock);
1350 pthread_join(out->offload_thread, (void **) NULL);
1351 pthread_cond_destroy(&out->offload_cond);
1352
1353 return 0;
1354}
1355
Eric Laurent07eeafd2013-10-06 12:52:49 -07001356static bool allow_hdmi_channel_config(struct audio_device *adev)
1357{
1358 struct listnode *node;
1359 struct audio_usecase *usecase;
1360 bool ret = true;
1361
1362 list_for_each(node, &adev->usecase_list) {
1363 usecase = node_to_item(node, struct audio_usecase, list);
1364 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1365 /*
1366 * If voice call is already existing, do not proceed further to avoid
1367 * disabling/enabling both RX and TX devices, CSD calls, etc.
1368 * Once the voice call done, the HDMI channels can be configured to
1369 * max channels of remaining use cases.
1370 */
1371 if (usecase->id == USECASE_VOICE_CALL) {
1372 ALOGD("%s: voice call is active, no change in HDMI channels",
1373 __func__);
1374 ret = false;
1375 break;
1376 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1377 ALOGD("%s: multi channel playback is active, "
1378 "no change in HDMI channels", __func__);
1379 ret = false;
1380 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001381 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001382 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001383 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1384 ", no change in HDMI channels", __func__,
1385 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001386 ret = false;
1387 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 }
1389 }
1390 }
1391 return ret;
1392}
1393
1394static int check_and_set_hdmi_channels(struct audio_device *adev,
1395 unsigned int channels)
1396{
1397 struct listnode *node;
1398 struct audio_usecase *usecase;
1399
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001400 unsigned int supported_channels = platform_edid_get_max_channels(
1401 adev->platform);
1402 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403 /* Check if change in HDMI channel config is allowed */
1404 if (!allow_hdmi_channel_config(adev))
1405 return 0;
1406
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001407 if (channels > supported_channels)
1408 channels = supported_channels;
1409
Eric Laurent07eeafd2013-10-06 12:52:49 -07001410 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001411 ALOGD("%s: Requested channels are same as current channels(%d)",
1412 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 return 0;
1414 }
1415
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001416 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001418 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 adev->cur_hdmi_channels = channels;
1420
1421 /*
1422 * Deroute all the playback streams routed to HDMI so that
1423 * the back end is deactivated. Note that backend will not
1424 * be deactivated if any one stream is connected to it.
1425 */
1426 list_for_each(node, &adev->usecase_list) {
1427 usecase = node_to_item(node, struct audio_usecase, list);
1428 if (usecase->type == PCM_PLAYBACK &&
1429 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001430 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 }
1432 }
1433
1434 /*
1435 * Enable all the streams disabled above. Now the HDMI backend
1436 * will be activated with new channel configuration
1437 */
1438 list_for_each(node, &adev->usecase_list) {
1439 usecase = node_to_item(node, struct audio_usecase, list);
1440 if (usecase->type == PCM_PLAYBACK &&
1441 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001442 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001443 }
1444 }
1445
1446 return 0;
1447}
1448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449static int stop_output_stream(struct stream_out *out)
1450{
1451 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 struct audio_usecase *uc_info;
1453 struct audio_device *adev = out->dev;
1454
Eric Laurent994a6932013-07-17 11:51:42 -07001455 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 uc_info = get_usecase_from_list(adev, out->usecase);
1458 if (uc_info == NULL) {
1459 ALOGE("%s: Could not find the usecase (%d) in the list",
1460 __func__, out->usecase);
1461 return -EINVAL;
1462 }
1463
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001464 if (is_offload_usecase(out->usecase) &&
1465 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001466 if (adev->visualizer_stop_output != NULL)
1467 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001468
1469 audio_extn_dts_remove_state_notifier_node(out->usecase);
1470
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001471 if (adev->offload_effects_stop_output != NULL)
1472 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1473 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001474
Eric Laurent150dbfe2013-02-27 14:31:02 -08001475 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001476 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477
1478 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001479 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001481 list_remove(&uc_info->list);
1482 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001484 if (is_offload_usecase(out->usecase) &&
1485 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1486 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1487 ALOGV("Disable passthrough , reset mixer to pcm");
1488 /* NO_PASSTHROUGH */
1489 out->compr_config.codec->compr_passthr = 0;
1490 audio_extn_dolby_set_hdmi_config(adev, out);
1491 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1492 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001493 /* Must be called after removing the usecase from list */
1494 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1495 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1496
Eric Laurent994a6932013-07-17 11:51:42 -07001497 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 return ret;
1499}
1500
1501int start_output_stream(struct stream_out *out)
1502{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001504 int sink_channels = 0;
1505 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 struct audio_usecase *uc_info;
1507 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301508 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001510 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1511 ret = -EINVAL;
1512 goto error_config;
1513 }
1514
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301515 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1516 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1517 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301518
Naresh Tanniru80659832014-06-04 18:17:56 +05301519 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301520 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301521 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301522 goto error_config;
1523 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301524
Eric Laurentb23d5282013-05-14 15:27:20 -07001525 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 if (out->pcm_device_id < 0) {
1527 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1528 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001529 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001530 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 }
1532
1533 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001534
1535 if (!uc_info) {
1536 ret = -ENOMEM;
1537 goto error_config;
1538 }
1539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 uc_info->id = out->usecase;
1541 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001542 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 uc_info->devices = out->devices;
1544 uc_info->in_snd_device = SND_DEVICE_NONE;
1545 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001547 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001548 if (is_offload_usecase(out->usecase)) {
1549 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001550 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1551 }
1552 }
Mingming Yin9c041392014-05-01 15:37:31 -07001553 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1554 if (!strncmp("true", prop_value, 4)) {
1555 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001556 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1557 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001558 check_and_set_hdmi_channels(adev, sink_channels);
1559 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 if (is_offload_usecase(out->usecase)) {
1561 unsigned int ch_count = out->compr_config.codec->ch_in;
1562 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1563 /* backend channel config for passthrough stream is stereo */
1564 ch_count = 2;
1565 check_and_set_hdmi_channels(adev, ch_count);
1566 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001567 check_and_set_hdmi_channels(adev, out->config.channels);
1568 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001569 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001570 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001571 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 select_devices(adev, out->usecase);
1574
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1576 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001577 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001578 unsigned int flags = PCM_OUT;
1579 unsigned int pcm_open_retry_count = 0;
1580 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1581 flags |= PCM_MMAP | PCM_NOIRQ;
1582 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1583 } else
1584 flags |= PCM_MONOTONIC;
1585
1586 while (1) {
1587 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1588 flags, &out->config);
1589 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1590 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1591 if (out->pcm != NULL) {
1592 pcm_close(out->pcm);
1593 out->pcm = NULL;
1594 }
1595 if (pcm_open_retry_count-- == 0) {
1596 ret = -EIO;
1597 goto error_open;
1598 }
1599 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1600 continue;
1601 }
1602 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001604 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1605 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001607 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1608 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001610 out->compr = compress_open(adev->snd_card,
1611 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 COMPRESS_IN, &out->compr_config);
1613 if (out->compr && !is_compress_ready(out->compr)) {
1614 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1615 compress_close(out->compr);
1616 out->compr = NULL;
1617 ret = -EIO;
1618 goto error_open;
1619 }
1620 if (out->offload_callback)
1621 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001622
Fred Oh3f43e742015-03-04 18:42:34 -08001623 /* Since small bufs uses blocking writes, a write will be blocked
1624 for the default max poll time (20s) in the event of an SSR.
1625 Reduce the poll time to observe and deal with SSR faster.
1626 */
1627 if (out->use_small_bufs) {
1628 compress_set_max_poll_wait(out->compr, 1000);
1629 }
1630
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001631 audio_extn_dts_create_state_notifier_node(out->usecase);
1632 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1633 popcount(out->channel_mask),
1634 out->playback_started);
1635
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001636#ifdef DS1_DOLBY_DDP_ENABLED
1637 if (audio_extn_is_dolby_format(out->format))
1638 audio_extn_dolby_send_ddp_endp_params(adev);
1639#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001640 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1641 if (adev->visualizer_start_output != NULL)
1642 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1643 if (adev->offload_effects_start_output != NULL)
1644 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001645 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 }
Eric Laurent994a6932013-07-17 11:51:42 -07001648 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001650error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001652error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001653 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654}
1655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656static int check_input_parameters(uint32_t sample_rate,
1657 audio_format_t format,
1658 int channel_count)
1659{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001660 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001662 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001663 !voice_extn_compress_voip_is_format_supported(format) &&
1664 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001665
1666 switch (channel_count) {
1667 case 1:
1668 case 2:
1669 case 6:
1670 break;
1671 default:
1672 ret = -EINVAL;
1673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
1675 switch (sample_rate) {
1676 case 8000:
1677 case 11025:
1678 case 12000:
1679 case 16000:
1680 case 22050:
1681 case 24000:
1682 case 32000:
1683 case 44100:
1684 case 48000:
1685 break;
1686 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001687 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 }
1689
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001690 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691}
1692
1693static size_t get_input_buffer_size(uint32_t sample_rate,
1694 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001695 int channel_count,
1696 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697{
1698 size_t size = 0;
1699
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001700 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1701 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001703 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001704 if (is_low_latency)
1705 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001706 /* ToDo: should use frame_size computed based on the format and
1707 channel_count here. */
1708 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001710 /* make sure the size is multiple of 32 bytes
1711 * At 48 kHz mono 16-bit PCM:
1712 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1713 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1714 */
1715 size += 0x1f;
1716 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001717
1718 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719}
1720
1721static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1722{
1723 struct stream_out *out = (struct stream_out *)stream;
1724
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001728static int out_set_sample_rate(struct audio_stream *stream __unused,
1729 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730{
1731 return -ENOSYS;
1732}
1733
1734static size_t out_get_buffer_size(const struct audio_stream *stream)
1735{
1736 struct stream_out *out = (struct stream_out *)stream;
1737
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001738 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001740 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1741 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001743 return out->config.period_size *
1744 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745}
1746
1747static uint32_t out_get_channels(const struct audio_stream *stream)
1748{
1749 struct stream_out *out = (struct stream_out *)stream;
1750
1751 return out->channel_mask;
1752}
1753
1754static audio_format_t out_get_format(const struct audio_stream *stream)
1755{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 struct stream_out *out = (struct stream_out *)stream;
1757
1758 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759}
1760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001761static int out_set_format(struct audio_stream *stream __unused,
1762 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763{
1764 return -ENOSYS;
1765}
1766
1767static int out_standby(struct audio_stream *stream)
1768{
1769 struct stream_out *out = (struct stream_out *)stream;
1770 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301772 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1773 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001774 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1775 /* Ignore standby in case of voip call because the voip output
1776 * stream is closed in adev_close_output_stream()
1777 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301778 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 return 0;
1780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001784 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001786 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001787 if (out->pcm) {
1788 pcm_close(out->pcm);
1789 out->pcm = NULL;
1790 }
1791 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001792 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001794 out->gapless_mdata.encoder_delay = 0;
1795 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 if (out->compr != NULL) {
1797 compress_close(out->compr);
1798 out->compr = NULL;
1799 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001802 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 }
1804 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001805 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 return 0;
1807}
1808
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001809static int out_dump(const struct audio_stream *stream __unused,
1810 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811{
1812 return 0;
1813}
1814
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001815static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1816{
1817 int ret = 0;
1818 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301819 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001820
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001822 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 return -EINVAL;
1824 }
1825
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001826 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1827 if (ret >= 0) {
1828 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1829 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1830 ALOGV("ADTS format is set in offload mode");
1831 }
Yadav Anamikafbcef792015-08-19 16:15:00 +05301832 out->send_new_metadata = 1;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001833 }
1834
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301835 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001836
Yadav Anamikafbcef792015-08-19 16:15:00 +05301837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1838 if(ret >= 0)
1839 is_meta_data_params = true;
1840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1841 if(ret >= 0)
1842 is_meta_data_params = true;
1843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1844 if(ret >= 0)
1845 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001846 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1847 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301848 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301849 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1852 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301853 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301854 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 }
1856
Yadav Anamikafbcef792015-08-19 16:15:00 +05301857 if(!is_meta_data_params) {
1858 ALOGV("%s: Not gapless meta data params", __func__);
1859 return 0;
1860 }
1861 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 ALOGV("%s new encoder delay %u and padding %u", __func__,
1863 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1864
1865 return 0;
1866}
1867
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001868static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1869{
1870 return out == adev->primary_output || out == adev->voice_tx_output;
1871}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1874{
1875 struct stream_out *out = (struct stream_out *)stream;
1876 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001877 struct audio_usecase *usecase;
1878 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 struct str_parms *parms;
1880 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001881 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001882 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883
sangwoobc677242013-08-08 16:53:43 +09001884 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301887 if (!parms)
1888 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001889 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1890 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001893 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301896 * When HDMI cable is unplugged/usb hs is disconnected the
1897 * music playback is paused and the policy manager sends routing=0
1898 * But the audioflingercontinues to write data until standby time
1899 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 * Avoid this by routing audio to speaker until standby.
1901 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301902 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1903 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001905 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1906 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 }
1908
1909 /*
1910 * select_devices() call below switches all the usecases on the same
1911 * backend to the new device. Refer to check_usecases_codec_backend() in
1912 * the select_devices(). But how do we undo this?
1913 *
1914 * For example, music playback is active on headset (deep-buffer usecase)
1915 * and if we go to ringtones and select a ringtone, low-latency usecase
1916 * will be started on headset+speaker. As we can't enable headset+speaker
1917 * and headset devices at the same time, select_devices() switches the music
1918 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1919 * So when the ringtone playback is completed, how do we undo the same?
1920 *
1921 * We are relying on the out_set_parameters() call on deep-buffer output,
1922 * once the ringtone playback is ended.
1923 * NOTE: We should not check if the current devices are same as new devices.
1924 * Because select_devices() must be called to switch back the music
1925 * playback to headset.
1926 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001927 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001928 out->devices = val;
1929
1930 if (!out->standby)
1931 select_devices(adev, out->usecase);
1932
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001933 if (output_drives_call(adev, out)) {
1934 if(!voice_is_in_call(adev)) {
1935 if (adev->mode == AUDIO_MODE_IN_CALL) {
1936 adev->current_call_output = out;
1937 ret = voice_start_call(adev);
1938 }
1939 } else {
1940 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001941 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001942 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001943 }
1944 }
1945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001947 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001949
1950 if (out == adev->primary_output) {
1951 pthread_mutex_lock(&adev->lock);
1952 audio_extn_set_parameters(adev, parms);
1953 pthread_mutex_unlock(&adev->lock);
1954 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001955 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001956 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001957 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001958
1959 audio_extn_dts_create_state_notifier_node(out->usecase);
1960 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1961 popcount(out->channel_mask),
1962 out->playback_started);
1963
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001964 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001965 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301968error:
Eric Laurent994a6932013-07-17 11:51:42 -07001969 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 return ret;
1971}
1972
1973static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976 struct str_parms *query = str_parms_create_str(keys);
1977 char *str;
1978 char value[256];
1979 struct str_parms *reply = str_parms_create();
1980 size_t i, j;
1981 int ret;
1982 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001983
1984 if (!query || !reply) {
1985 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1986 return NULL;
1987 }
1988
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1991 if (ret >= 0) {
1992 value[0] = '\0';
1993 i = 0;
1994 while (out->supported_channel_masks[i] != 0) {
1995 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1996 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1997 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001998 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002000 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 first = false;
2002 break;
2003 }
2004 }
2005 i++;
2006 }
2007 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2008 str = str_parms_to_str(reply);
2009 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002010 voice_extn_out_get_parameters(out, query, reply);
2011 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002012 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002013 free(str);
2014 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002017
2018 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2019 if (ret >= 0) {
2020 value[0] = '\0';
2021 i = 0;
2022 first = true;
2023 while (out->supported_formats[i] != 0) {
2024 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2025 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2026 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002027 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002028 }
2029 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2030 first = false;
2031 break;
2032 }
2033 }
2034 i++;
2035 }
2036 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2037 str = str_parms_to_str(reply);
2038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 str_parms_destroy(query);
2040 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return str;
2043}
2044
2045static uint32_t out_get_latency(const struct audio_stream_out *stream)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002048 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Alexy Josephaa54c872014-12-03 02:46:47 -08002050 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002051 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002052 } else {
2053 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002055 }
2056
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302057 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002058 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059}
2060
2061static int out_set_volume(struct audio_stream_out *stream, float left,
2062 float right)
2063{
Eric Laurenta9024de2013-04-04 09:19:12 -07002064 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 int volume[2];
2066
Eric Laurenta9024de2013-04-04 09:19:12 -07002067 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2068 /* only take left channel into account: the API is for stereo anyway */
2069 out->muted = (left == 0.0f);
2070 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002071 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002072 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2073 /*
2074 * Set mute or umute on HDMI passthrough stream.
2075 * Only take left channel into account.
2076 * Mute is 0 and unmute 1
2077 */
2078 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2079 } else {
2080 char mixer_ctl_name[128];
2081 struct audio_device *adev = out->dev;
2082 struct mixer_ctl *ctl;
2083 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002084 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002086 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2087 "Compress Playback %d Volume", pcm_device_id);
2088 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2089 if (!ctl) {
2090 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2091 __func__, mixer_ctl_name);
2092 return -EINVAL;
2093 }
2094 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2095 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2096 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2097 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002099 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return -ENOSYS;
2102}
2103
2104static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2105 size_t bytes)
2106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302109 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002110 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302113
Naresh Tanniru80659832014-06-04 18:17:56 +05302114 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002115 // increase written size during SSR to avoid mismatch
2116 // with the written frames count in AF
2117 if (!is_offload_usecase(out->usecase))
2118 out->written += bytes / (out->config.channels * sizeof(short));
2119
Naresh Tanniru80659832014-06-04 18:17:56 +05302120 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302121 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302122 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302123 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002124 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302125 //during SSR for compress usecase we should return error to flinger
2126 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2127 pthread_mutex_unlock(&out->lock);
2128 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302129 }
2130 }
2131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002133 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002135 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2136 ret = voice_extn_compress_voip_start_output_stream(out);
2137 else
2138 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002139 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002142 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 goto exit;
2144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302147 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2148 setChannelStatus(out, buffer, bytes);
2149 adev->mChannelStatusSet = true;
2150 }
2151
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002152 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002153 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002155 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002156 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2157 out->send_new_metadata = 0;
2158 }
2159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302161 if (ret < 0)
2162 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002164 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302165 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302167 } else if (-ENETRESET == ret) {
2168 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2169 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2170 pthread_mutex_unlock(&out->lock);
2171 out_standby(&out->stream.common);
2172 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302174 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002176 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 out->playback_started = 1;
2178 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002179
2180 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2181 popcount(out->channel_mask),
2182 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 }
2184 pthread_mutex_unlock(&out->lock);
2185 return ret;
2186 } else {
2187 if (out->pcm) {
2188 if (out->muted)
2189 memset((void *)buffer, 0, bytes);
2190 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002191 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2192 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2193 else
2194 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302195 if (ret < 0)
2196 ret = -errno;
2197 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002198 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 }
2201
2202exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302203 /* ToDo: There may be a corner case when SSR happens back to back during
2204 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302207 }
2208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 pthread_mutex_unlock(&out->lock);
2210
2211 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002212 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002213 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302214 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302215 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302216 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302217 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302218 out->standby = true;
2219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002221 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302222 out_get_sample_rate(&out->stream.common));
2223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 }
2225 return bytes;
2226}
2227
2228static int out_get_render_position(const struct audio_stream_out *stream,
2229 uint32_t *dsp_frames)
2230{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302232 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002233
2234 if (dsp_frames == NULL)
2235 return -EINVAL;
2236
2237 *dsp_frames = 0;
2238 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002239 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 pthread_mutex_lock(&out->lock);
2241 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302242 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302244 if (ret < 0)
2245 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 ALOGVV("%s rendered frames %d sample_rate %d",
2247 __func__, *dsp_frames, out->sample_rate);
2248 }
2249 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302250 if (-ENETRESET == ret) {
2251 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2252 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2253 return -EINVAL;
2254 } else if(ret < 0) {
2255 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2256 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302257 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2258 /*
2259 * Handle corner case where compress session is closed during SSR
2260 * and timestamp is queried
2261 */
2262 ALOGE(" ERROR: sound card not active, return error");
2263 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302264 } else {
2265 return 0;
2266 }
Zhou Song32a556e2015-05-05 10:46:56 +08002267 } else if (audio_is_linear_pcm(out->format)) {
2268 *dsp_frames = out->written;
2269 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002270 } else
2271 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272}
2273
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002274static int out_add_audio_effect(const struct audio_stream *stream __unused,
2275 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276{
2277 return 0;
2278}
2279
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002280static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2281 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282{
2283 return 0;
2284}
2285
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002286static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2287 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288{
2289 return -EINVAL;
2290}
2291
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002292static int out_get_presentation_position(const struct audio_stream_out *stream,
2293 uint64_t *frames, struct timespec *timestamp)
2294{
2295 struct stream_out *out = (struct stream_out *)stream;
2296 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002297 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002298
2299 pthread_mutex_lock(&out->lock);
2300
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002301 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002302 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302303 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002304 &out->sample_rate);
2305 ALOGVV("%s rendered frames %ld sample_rate %d",
2306 __func__, dsp_frames, out->sample_rate);
2307 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302308 if (ret < 0)
2309 ret = -errno;
2310 if (-ENETRESET == ret) {
2311 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2312 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2313 ret = -EINVAL;
2314 } else
2315 ret = 0;
2316
Eric Laurent949a0892013-09-20 09:20:13 -07002317 /* this is the best we can do */
2318 clock_gettime(CLOCK_MONOTONIC, timestamp);
2319 }
2320 } else {
2321 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002322 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002323 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2324 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002325 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002326 // This adjustment accounts for buffering after app processor.
2327 // It is based on estimated DSP latency per use case, rather than exact.
2328 signed_frames -=
2329 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2330
Eric Laurent949a0892013-09-20 09:20:13 -07002331 // It would be unusual for this value to be negative, but check just in case ...
2332 if (signed_frames >= 0) {
2333 *frames = signed_frames;
2334 ret = 0;
2335 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002336 }
2337 }
2338 }
2339
2340 pthread_mutex_unlock(&out->lock);
2341
2342 return ret;
2343}
2344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345static int out_set_callback(struct audio_stream_out *stream,
2346 stream_callback_t callback, void *cookie)
2347{
2348 struct stream_out *out = (struct stream_out *)stream;
2349
2350 ALOGV("%s", __func__);
2351 pthread_mutex_lock(&out->lock);
2352 out->offload_callback = callback;
2353 out->offload_cookie = cookie;
2354 pthread_mutex_unlock(&out->lock);
2355 return 0;
2356}
2357
2358static int out_pause(struct audio_stream_out* stream)
2359{
2360 struct stream_out *out = (struct stream_out *)stream;
2361 int status = -ENOSYS;
2362 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002363 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002364 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002365 pthread_mutex_lock(&out->lock);
2366 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302367 struct audio_device *adev = out->dev;
2368 int snd_scard_state = get_snd_card_state(adev);
2369
2370 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2371 status = compress_pause(out->compr);
2372
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302375 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002376 audio_extn_dts_notify_playback_state(out->usecase, 0,
2377 out->sample_rate, popcount(out->channel_mask),
2378 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 }
2380 pthread_mutex_unlock(&out->lock);
2381 }
2382 return status;
2383}
2384
2385static int out_resume(struct audio_stream_out* stream)
2386{
2387 struct stream_out *out = (struct stream_out *)stream;
2388 int status = -ENOSYS;
2389 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002390 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002391 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 status = 0;
2393 pthread_mutex_lock(&out->lock);
2394 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302395 struct audio_device *adev = out->dev;
2396 int snd_scard_state = get_snd_card_state(adev);
2397
2398 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2399 status = compress_resume(out->compr);
2400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302403 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002404 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2405 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 }
2407 pthread_mutex_unlock(&out->lock);
2408 }
2409 return status;
2410}
2411
2412static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2413{
2414 struct stream_out *out = (struct stream_out *)stream;
2415 int status = -ENOSYS;
2416 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002417 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418 pthread_mutex_lock(&out->lock);
2419 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2420 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2421 else
2422 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2423 pthread_mutex_unlock(&out->lock);
2424 }
2425 return status;
2426}
2427
2428static int out_flush(struct audio_stream_out* stream)
2429{
2430 struct stream_out *out = (struct stream_out *)stream;
2431 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002432 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002433 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 pthread_mutex_lock(&out->lock);
2435 stop_compressed_output_l(out);
2436 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002437 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002438 return 0;
2439 }
2440 return -ENOSYS;
2441}
2442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443/** audio_stream_in implementation **/
2444static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2445{
2446 struct stream_in *in = (struct stream_in *)stream;
2447
2448 return in->config.rate;
2449}
2450
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002451static int in_set_sample_rate(struct audio_stream *stream __unused,
2452 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453{
2454 return -ENOSYS;
2455}
2456
2457static size_t in_get_buffer_size(const struct audio_stream *stream)
2458{
2459 struct stream_in *in = (struct stream_in *)stream;
2460
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002461 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2462 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002463 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2464 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002465
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002466 return in->config.period_size *
2467 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468}
2469
2470static uint32_t in_get_channels(const struct audio_stream *stream)
2471{
2472 struct stream_in *in = (struct stream_in *)stream;
2473
2474 return in->channel_mask;
2475}
2476
2477static audio_format_t in_get_format(const struct audio_stream *stream)
2478{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002479 struct stream_in *in = (struct stream_in *)stream;
2480
2481 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482}
2483
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002484static int in_set_format(struct audio_stream *stream __unused,
2485 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486{
2487 return -ENOSYS;
2488}
2489
2490static int in_standby(struct audio_stream *stream)
2491{
2492 struct stream_in *in = (struct stream_in *)stream;
2493 struct audio_device *adev = in->dev;
2494 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302495 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2496 stream, in->usecase, use_case_table[in->usecase]);
2497
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002498 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2499 /* Ignore standby in case of voip call because the voip input
2500 * stream is closed in adev_close_input_stream()
2501 */
2502 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2503 return status;
2504 }
2505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002507 if (!in->standby && in->is_st_session) {
2508 ALOGD("%s: sound trigger pcm stop lab", __func__);
2509 audio_extn_sound_trigger_stop_lab(in);
2510 in->standby = 1;
2511 }
2512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002514 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 if (in->pcm) {
2517 pcm_close(in->pcm);
2518 in->pcm = NULL;
2519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002521 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 }
2523 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002524 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 return status;
2526}
2527
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002528static int in_dump(const struct audio_stream *stream __unused,
2529 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530{
2531 return 0;
2532}
2533
2534static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2535{
2536 struct stream_in *in = (struct stream_in *)stream;
2537 struct audio_device *adev = in->dev;
2538 struct str_parms *parms;
2539 char *str;
2540 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002541 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302543 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 parms = str_parms_create_str(kvpairs);
2545
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302546 if (!parms)
2547 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002549 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002550
2551 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2552 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 val = atoi(value);
2554 /* no audio source uses val == 0 */
2555 if ((in->source != val) && (val != 0)) {
2556 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002557 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2558 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2559 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2560 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002561 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002562 err = voice_extn_compress_voip_open_input_stream(in);
2563 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002564 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002565 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002566 }
2567 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 }
2569 }
2570
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002571 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2572 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002574 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 in->device = val;
2576 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002577 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002578 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 }
2580 }
2581
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002582done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002584 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585
2586 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302587error:
Eric Laurent994a6932013-07-17 11:51:42 -07002588 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 return ret;
2590}
2591
2592static char* in_get_parameters(const struct audio_stream *stream,
2593 const char *keys)
2594{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002595 struct stream_in *in = (struct stream_in *)stream;
2596 struct str_parms *query = str_parms_create_str(keys);
2597 char *str;
2598 char value[256];
2599 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002600
2601 if (!query || !reply) {
2602 ALOGE("in_get_parameters: failed to create query or reply");
2603 return NULL;
2604 }
2605
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002606 ALOGV("%s: enter: keys - %s", __func__, keys);
2607
2608 voice_extn_in_get_parameters(in, query, reply);
2609
2610 str = str_parms_to_str(reply);
2611 str_parms_destroy(query);
2612 str_parms_destroy(reply);
2613
2614 ALOGV("%s: exit: returns - %s", __func__, str);
2615 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616}
2617
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002618static int in_set_gain(struct audio_stream_in *stream __unused,
2619 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620{
2621 return 0;
2622}
2623
2624static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2625 size_t bytes)
2626{
2627 struct stream_in *in = (struct stream_in *)stream;
2628 struct audio_device *adev = in->dev;
2629 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302630 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002634 if (in->is_st_session) {
2635 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2636 /* Read from sound trigger HAL */
2637 audio_extn_sound_trigger_read(in, buffer, bytes);
2638 pthread_mutex_unlock(&in->lock);
2639 return bytes;
2640 }
2641
2642 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2643 ALOGD(" %s: sound card is not active/SSR state", __func__);
2644 ret= -EIO;;
2645 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302646 }
2647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002649 pthread_mutex_lock(&adev->lock);
2650 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2651 ret = voice_extn_compress_voip_start_input_stream(in);
2652 else
2653 ret = start_input_stream(in);
2654 pthread_mutex_unlock(&adev->lock);
2655 if (ret != 0) {
2656 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 }
2658 in->standby = 0;
2659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
2661 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002662 if (audio_extn_ssr_get_enabled() &&
2663 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002664 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002665 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2666 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002667 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2668 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002669 else
2670 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302671 if (ret < 0)
2672 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 }
2674
2675 /*
2676 * Instead of writing zeroes here, we could trust the hardware
2677 * to always provide zeroes when muted.
2678 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302679 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2680 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 memset(buffer, 0, bytes);
2682
2683exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302684 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302685 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002686 if (-ENETRESET == ret)
2687 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 pthread_mutex_unlock(&in->lock);
2690
2691 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302692 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302693 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302694 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302695 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302696 in->standby = true;
2697 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302698 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002700 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002701 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302702 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 }
2704 return bytes;
2705}
2706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002707static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
2709 return 0;
2710}
2711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712static int add_remove_audio_effect(const struct audio_stream *stream,
2713 effect_handle_t effect,
2714 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002716 struct stream_in *in = (struct stream_in *)stream;
2717 int status = 0;
2718 effect_descriptor_t desc;
2719
2720 status = (*effect)->get_descriptor(effect, &desc);
2721 if (status != 0)
2722 return status;
2723
2724 pthread_mutex_lock(&in->lock);
2725 pthread_mutex_lock(&in->dev->lock);
2726 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2727 in->enable_aec != enable &&
2728 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2729 in->enable_aec = enable;
2730 if (!in->standby)
2731 select_devices(in->dev, in->usecase);
2732 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002733 if (in->enable_ns != enable &&
2734 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2735 in->enable_ns = enable;
2736 if (!in->standby)
2737 select_devices(in->dev, in->usecase);
2738 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002739 pthread_mutex_unlock(&in->dev->lock);
2740 pthread_mutex_unlock(&in->lock);
2741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 return 0;
2743}
2744
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002745static int in_add_audio_effect(const struct audio_stream *stream,
2746 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747{
Eric Laurent994a6932013-07-17 11:51:42 -07002748 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002749 return add_remove_audio_effect(stream, effect, true);
2750}
2751
2752static int in_remove_audio_effect(const struct audio_stream *stream,
2753 effect_handle_t effect)
2754{
Eric Laurent994a6932013-07-17 11:51:42 -07002755 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002756 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757}
2758
2759static int adev_open_output_stream(struct audio_hw_device *dev,
2760 audio_io_handle_t handle,
2761 audio_devices_t devices,
2762 audio_output_flags_t flags,
2763 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002764 struct audio_stream_out **stream_out,
2765 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766{
2767 struct audio_device *adev = (struct audio_device *)dev;
2768 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002769 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002770 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302773
2774 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2775 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2776 ALOGE(" sound card is not active rejecting compress output open request");
2777 return -EINVAL;
2778 }
2779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2781
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302782 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2783 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2784 devices, flags, &out->stream);
2785
2786
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002787 if (!out) {
2788 return -ENOMEM;
2789 }
2790
Haynes Mathew George204045b2015-02-25 20:32:03 -08002791 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2792 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 if (devices == AUDIO_DEVICE_NONE)
2795 devices = AUDIO_DEVICE_OUT_SPEAKER;
2796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 out->flags = flags;
2798 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002799 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002800 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 out->sample_rate = config->sample_rate;
2802 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2803 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002804 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002805 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002806 out->non_blocking = 0;
2807 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302809 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2810 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002811 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2812 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2813
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002814 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002815 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2816 ret = read_hdmi_channel_masks(out);
2817
2818 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2819 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002820 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002821 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002822 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002823
2824 if (config->sample_rate == 0)
2825 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2826 if (config->channel_mask == 0)
2827 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2828
2829 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2832 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002834 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002836 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2837 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002838 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002839 ret = voice_extn_compress_voip_open_output_stream(out);
2840 if (ret != 0) {
2841 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2842 __func__, ret);
2843 goto error_open;
2844 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2846 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2847 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2848 ALOGE("%s: Unsupported Offload information", __func__);
2849 ret = -EINVAL;
2850 goto error_open;
2851 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002852
2853 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2854 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2855 ALOGV("read and update_pass through formats");
2856 ret = audio_extn_dolby_update_passt_formats(adev, out);
2857 if(ret != 0) {
2858 goto error_open;
2859 }
2860 if(config->offload_info.format == 0)
2861 config->offload_info.format = out->supported_formats[0];
2862 }
2863
Mingming Yin90310102013-11-13 16:57:00 -08002864 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002865 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 ALOGE("%s: Unsupported audio format", __func__);
2867 ret = -EINVAL;
2868 goto error_open;
2869 }
2870
2871 out->compr_config.codec = (struct snd_codec *)
2872 calloc(1, sizeof(struct snd_codec));
2873
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002874 if (!out->compr_config.codec) {
2875 ret = -ENOMEM;
2876 goto error_open;
2877 }
2878
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002879 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 if (config->offload_info.channel_mask)
2881 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002882 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002884 config->offload_info.channel_mask = config->channel_mask;
2885 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002886 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 out->sample_rate = config->offload_info.sample_rate;
2888
2889 out->stream.set_callback = out_set_callback;
2890 out->stream.pause = out_pause;
2891 out->stream.resume = out_resume;
2892 out->stream.drain = out_drain;
2893 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002894 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002896 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002897 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002898 audio_extn_dolby_get_snd_codec_id(adev, out,
2899 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002900 else
2901 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302903 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002904 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002905 platform_get_pcm_offload_buffer_size(&config->offload_info);
2906 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2907 out->compr_config.fragment_size =
2908 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002909 } else {
2910 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002911 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002912 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2914 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002915 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 out->compr_config.codec->bit_rate =
2917 config->offload_info.bit_rate;
2918 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002919 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302921 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002922 /*TODO: Do we need to change it for passthrough */
2923 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924
Mingming Yin3ee55c62014-08-04 14:23:35 -07002925 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2926 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002927 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2928 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002929 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002930 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2931
Mingming Yin3ee55c62014-08-04 14:23:35 -07002932 if (out->bit_width == 24) {
2933 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2934 }
2935
Amit Shekhar6f461b12014-08-01 14:52:58 -07002936 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302937 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2940 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002941
Sharad Sangleb27354b2015-06-18 15:58:55 +05302942 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002943 //this flag is set from framework only if its for PCM formats
2944 //no need to check for PCM format again
2945 out->non_blocking = 0;
2946 out->use_small_bufs = true;
2947 ALOGI("Keep write blocking for small buff: non_blockling %d",
2948 out->non_blocking);
2949 }
2950
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002951 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002952 out->offload_state = OFFLOAD_STATE_IDLE;
2953 out->playback_started = 0;
2954
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002955 audio_extn_dts_create_state_notifier_node(out->usecase);
2956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 create_offload_callback_thread(out);
2958 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2959 __func__, config->offload_info.version,
2960 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002961 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002962 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002963 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2964 ret = voice_check_and_set_incall_music_usecase(adev, out);
2965 if (ret != 0) {
2966 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2967 __func__, ret);
2968 goto error_open;
2969 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002970 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2971 if (config->sample_rate == 0)
2972 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2973 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2974 config->sample_rate != 8000) {
2975 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2976 ret = -EINVAL;
2977 goto error_open;
2978 }
2979 out->sample_rate = config->sample_rate;
2980 out->config.rate = config->sample_rate;
2981 if (config->format == AUDIO_FORMAT_DEFAULT)
2982 config->format = AUDIO_FORMAT_PCM_16_BIT;
2983 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2984 config->format = AUDIO_FORMAT_PCM_16_BIT;
2985 ret = -EINVAL;
2986 goto error_open;
2987 }
2988 out->format = config->format;
2989 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2990 out->config = pcm_config_afe_proxy_playback;
2991 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002992 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002993 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2995 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002997 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2998 format = AUDIO_FORMAT_PCM_16_BIT;
2999 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3000 out->config = pcm_config_deep_buffer;
3001 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003002 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003003 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003004 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003005 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003006 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003007 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 }
3009
Amit Shekhar1d896042014-10-03 13:16:09 -07003010 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3011 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003012 /* TODO remove this hardcoding and check why width is zero*/
3013 if (out->bit_width == 0)
3014 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003015 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3016 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003017 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303018 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003019 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3020 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3021 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003022 if(adev->primary_output == NULL)
3023 adev->primary_output = out;
3024 else {
3025 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003026 ret = -EEXIST;
3027 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003028 }
3029 }
3030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 /* Check if this usecase is already existing */
3032 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003033 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3034 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003037 ret = -EEXIST;
3038 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 }
3040 pthread_mutex_unlock(&adev->lock);
3041
3042 out->stream.common.get_sample_rate = out_get_sample_rate;
3043 out->stream.common.set_sample_rate = out_set_sample_rate;
3044 out->stream.common.get_buffer_size = out_get_buffer_size;
3045 out->stream.common.get_channels = out_get_channels;
3046 out->stream.common.get_format = out_get_format;
3047 out->stream.common.set_format = out_set_format;
3048 out->stream.common.standby = out_standby;
3049 out->stream.common.dump = out_dump;
3050 out->stream.common.set_parameters = out_set_parameters;
3051 out->stream.common.get_parameters = out_get_parameters;
3052 out->stream.common.add_audio_effect = out_add_audio_effect;
3053 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3054 out->stream.get_latency = out_get_latency;
3055 out->stream.set_volume = out_set_volume;
3056 out->stream.write = out_write;
3057 out->stream.get_render_position = out_get_render_position;
3058 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003059 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003062 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064
3065 config->format = out->stream.common.get_format(&out->stream.common);
3066 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3067 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3068
3069 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303070 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3071 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003072
3073 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3074 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3075 popcount(out->channel_mask), out->playback_started);
3076
Eric Laurent994a6932013-07-17 11:51:42 -07003077 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003079
3080error_open:
3081 free(out);
3082 *stream_out = NULL;
3083 ALOGD("%s: exit: ret %d", __func__, ret);
3084 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085}
3086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003087static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 struct audio_stream_out *stream)
3089{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 struct stream_out *out = (struct stream_out *)stream;
3091 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003092 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303094 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3095
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003096 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303097 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003098 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303099 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003100 if(ret != 0)
3101 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3102 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003103 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003104 out_standby(&stream->common);
3105
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003106 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003107 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003109 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 if (out->compr_config.codec != NULL)
3111 free(out->compr_config.codec);
3112 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003113
3114 if (adev->voice_tx_output == out)
3115 adev->voice_tx_output = NULL;
3116
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 pthread_cond_destroy(&out->cond);
3118 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003120 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121}
3122
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003123static void close_compress_sessions(struct audio_device *adev)
3124{
Mingming Yin7b762e72015-03-04 13:47:32 -08003125 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303126 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003127 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003128 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303129
3130 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003131 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303132 if (is_offload_usecase(usecase->id)) {
3133 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003134 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3135 out = usecase->stream.out;
3136 pthread_mutex_unlock(&adev->lock);
3137 out_standby(&out->stream.common);
3138 pthread_mutex_lock(&adev->lock);
3139 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303140 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003141 }
3142 pthread_mutex_unlock(&adev->lock);
3143}
3144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3146{
3147 struct audio_device *adev = (struct audio_device *)dev;
3148 struct str_parms *parms;
3149 char *str;
3150 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003151 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003152 int ret;
3153 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003155 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303158 if (!parms)
3159 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003160 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3161 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303164 struct listnode *node;
3165 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303166 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303167 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003168 //close compress sessions on OFFLINE status
3169 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170 } else if (strstr(snd_card_status, "ONLINE")) {
3171 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303172 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303173 if (!platform_is_acdb_initialized(adev->platform)) {
3174 ret = platform_acdb_init(adev->platform);
3175 if(ret)
3176 ALOGE("acdb initialization is failed");
3177
3178 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303179 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303180 }
3181
3182 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003183 status = voice_set_parameters(adev, parms);
3184 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003185 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003187 status = platform_set_parameters(adev->platform, parms);
3188 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003189 goto done;
3190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003191 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3192 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003193 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3195 adev->bluetooth_nrec = true;
3196 else
3197 adev->bluetooth_nrec = false;
3198 }
3199
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003200 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3201 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3203 adev->screen_off = false;
3204 else
3205 adev->screen_off = true;
3206 }
3207
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003208 ret = str_parms_get_int(parms, "rotation", &val);
3209 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003210 bool reverse_speakers = false;
3211 switch(val) {
3212 // FIXME: note that the code below assumes that the speakers are in the correct placement
3213 // relative to the user when the device is rotated 90deg from its default rotation. This
3214 // assumption is device-specific, not platform-specific like this code.
3215 case 270:
3216 reverse_speakers = true;
3217 break;
3218 case 0:
3219 case 90:
3220 case 180:
3221 break;
3222 default:
3223 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003224 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003225 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003226 if (status == 0) {
3227 if (adev->speaker_lr_swap != reverse_speakers) {
3228 adev->speaker_lr_swap = reverse_speakers;
3229 // only update the selected device if there is active pcm playback
3230 struct audio_usecase *usecase;
3231 struct listnode *node;
3232 list_for_each(node, &adev->usecase_list) {
3233 usecase = node_to_item(node, struct audio_usecase, list);
3234 if (usecase->type == PCM_PLAYBACK) {
3235 select_devices(adev, usecase->id);
3236 break;
3237 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003238 }
3239 }
3240 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003241 }
3242
Mingming Yin514a8bc2014-07-29 15:22:21 -07003243 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3244 if (ret >= 0) {
3245 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3246 adev->bt_wb_speech_enabled = true;
3247 else
3248 adev->bt_wb_speech_enabled = false;
3249 }
3250
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3252 if (ret >= 0) {
3253 val = atoi(value);
3254 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3255 ALOGV("cache new edid");
3256 platform_cache_edid(adev->platform);
3257 }
3258 }
3259
3260 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3261 if (ret >= 0) {
3262 val = atoi(value);
3263 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3264 ALOGV("invalidate cached edid");
3265 platform_invalidate_edid(adev->platform);
3266 }
3267 }
3268
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003269 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003270
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003271done:
3272 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003273 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303274error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003275 ALOGV("%s: exit with code(%d)", __func__, status);
3276 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
3279static char* adev_get_parameters(const struct audio_hw_device *dev,
3280 const char *keys)
3281{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003282 struct audio_device *adev = (struct audio_device *)dev;
3283 struct str_parms *reply = str_parms_create();
3284 struct str_parms *query = str_parms_create_str(keys);
3285 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303286 char value[256] = {0};
3287 int ret = 0;
3288
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003289 if (!query || !reply) {
3290 ALOGE("adev_get_parameters: failed to create query or reply");
3291 return NULL;
3292 }
3293
Naresh Tannirud7205b62014-06-20 02:54:48 +05303294 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3295 sizeof(value));
3296 if (ret >=0) {
3297 int val = 1;
3298 pthread_mutex_lock(&adev->snd_card_status.lock);
3299 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3300 val = 0;
3301 pthread_mutex_unlock(&adev->snd_card_status.lock);
3302 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3303 goto exit;
3304 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003305
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003306 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003307 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003308 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003309 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303310 pthread_mutex_unlock(&adev->lock);
3311
Naresh Tannirud7205b62014-06-20 02:54:48 +05303312exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003313 str = str_parms_to_str(reply);
3314 str_parms_destroy(query);
3315 str_parms_destroy(reply);
3316
3317 ALOGV("%s: exit: returns - %s", __func__, str);
3318 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319}
3320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003321static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return 0;
3324}
3325
3326static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3327{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003328 int ret;
3329 struct audio_device *adev = (struct audio_device *)dev;
3330 pthread_mutex_lock(&adev->lock);
3331 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003332 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003333 pthread_mutex_unlock(&adev->lock);
3334 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335}
3336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003337static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3338 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339{
3340 return -ENOSYS;
3341}
3342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003343static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3344 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345{
3346 return -ENOSYS;
3347}
3348
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003349static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3350 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351{
3352 return -ENOSYS;
3353}
3354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003355static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3356 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357{
3358 return -ENOSYS;
3359}
3360
3361static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3362{
3363 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 pthread_mutex_lock(&adev->lock);
3366 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003367 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003369 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3370 voice_is_in_call(adev)) {
3371 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303372 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003373 adev->current_call_output = NULL;
3374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 }
3376 pthread_mutex_unlock(&adev->lock);
3377 return 0;
3378}
3379
3380static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3381{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003382 int ret;
3383
3384 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003385 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003386 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3387 pthread_mutex_unlock(&adev->lock);
3388
3389 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390}
3391
3392static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3393{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003394 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 return 0;
3396}
3397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003398static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 const struct audio_config *config)
3400{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003401 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003403 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3404 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405}
3406
3407static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003408 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 audio_devices_t devices,
3410 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003411 struct audio_stream_in **stream_in,
3412 audio_input_flags_t flags __unused,
3413 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003414 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415{
3416 struct audio_device *adev = (struct audio_device *)dev;
3417 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003418 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003419 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003420 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 *stream_in = NULL;
3423 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3424 return -EINVAL;
3425
3426 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003427
3428 if (!in) {
3429 ALOGE("failed to allocate input stream");
3430 return -ENOMEM;
3431 }
3432
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303433 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003434 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3435 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003437 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->stream.common.get_sample_rate = in_get_sample_rate;
3440 in->stream.common.set_sample_rate = in_set_sample_rate;
3441 in->stream.common.get_buffer_size = in_get_buffer_size;
3442 in->stream.common.get_channels = in_get_channels;
3443 in->stream.common.get_format = in_get_format;
3444 in->stream.common.set_format = in_set_format;
3445 in->stream.common.standby = in_standby;
3446 in->stream.common.dump = in_dump;
3447 in->stream.common.set_parameters = in_set_parameters;
3448 in->stream.common.get_parameters = in_get_parameters;
3449 in->stream.common.add_audio_effect = in_add_audio_effect;
3450 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3451 in->stream.set_gain = in_set_gain;
3452 in->stream.read = in_read;
3453 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3454
3455 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003456 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 in->standby = 1;
3459 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003460 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461
3462 /* Update config params with the requested sample rate and channels */
3463 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003464 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3465 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3466 is_low_latency = true;
3467#if LOW_LATENCY_CAPTURE_USE_CASE
3468 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3469#endif
3470 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003473 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003475 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303476 if (adev->mode != AUDIO_MODE_IN_CALL) {
3477 ret = -EINVAL;
3478 goto err_open;
3479 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003480 if (config->sample_rate == 0)
3481 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3482 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3483 config->sample_rate != 8000) {
3484 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3485 ret = -EINVAL;
3486 goto err_open;
3487 }
3488 if (config->format == AUDIO_FORMAT_DEFAULT)
3489 config->format = AUDIO_FORMAT_PCM_16_BIT;
3490 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3491 config->format = AUDIO_FORMAT_PCM_16_BIT;
3492 ret = -EINVAL;
3493 goto err_open;
3494 }
3495
3496 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3497 in->config = pcm_config_afe_proxy_record;
3498 in->config.channels = channel_count;
3499 in->config.rate = config->sample_rate;
3500 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003501 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003503 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3504 ret = -EINVAL;
3505 goto err_open;
3506 }
3507 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003508 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003509 }
Mingming Yine62d7842013-10-25 16:26:03 -07003510 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003511 audio_extn_compr_cap_format_supported(config->format) &&
3512 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003513 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003514 } else {
3515 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003516 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003517 buffer_size = get_input_buffer_size(config->sample_rate,
3518 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003519 channel_count,
3520 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003521 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003522 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3523 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3524 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3525 (in->config.rate == 8000 || in->config.rate == 16000) &&
3526 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3527 voice_extn_compress_voip_open_input_stream(in);
3528 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003531 /* This stream could be for sound trigger lab,
3532 get sound trigger pcm if present */
3533 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303534 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003537 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003538 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
3540err_open:
3541 free(in);
3542 *stream_in = NULL;
3543 return ret;
3544}
3545
3546static void adev_close_input_stream(struct audio_hw_device *dev,
3547 struct audio_stream_in *stream)
3548{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003550 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003551 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303552
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303553 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003554
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303555 /* Disable echo reference while closing input stream */
3556 platform_set_echo_reference(adev->platform, false);
3557
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003558 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303559 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003560 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303561 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003562 if (ret != 0)
3563 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3564 __func__, ret);
3565 } else
3566 in_standby(&stream->common);
3567
Mingming Yin7b762e72015-03-04 13:47:32 -08003568 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003569 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003570 audio_extn_ssr_deinit();
3571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
Mingming Yine62d7842013-10-25 16:26:03 -07003573 if(audio_extn_compr_cap_enabled() &&
3574 audio_extn_compr_cap_format_supported(in->config.format))
3575 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003576
3577 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 return;
3579}
3580
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003581static int adev_dump(const audio_hw_device_t *device __unused,
3582 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583{
3584 return 0;
3585}
3586
3587static int adev_close(hw_device_t *device)
3588{
3589 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003590
3591 if (!adev)
3592 return 0;
3593
3594 pthread_mutex_lock(&adev_init_lock);
3595
3596 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003597 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003598 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003599 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003600 audio_route_free(adev->audio_route);
3601 free(adev->snd_dev_ref_cnt);
3602 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003603 free(device);
3604 adev = NULL;
3605 }
3606 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 return 0;
3608}
3609
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003610/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3611 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3612 * just that it _might_ work.
3613 */
3614static int period_size_is_plausible_for_low_latency(int period_size)
3615{
3616 switch (period_size) {
3617 case 160:
3618 case 240:
3619 case 320:
3620 case 480:
3621 return 1;
3622 default:
3623 return 0;
3624 }
3625}
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627static int adev_open(const hw_module_t *module, const char *name,
3628 hw_device_t **device)
3629{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003630 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003632 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3634
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003635 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003636 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003637 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003638 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003639 ALOGD("%s: returning existing instance of adev", __func__);
3640 ALOGD("%s: exit", __func__);
3641 pthread_mutex_unlock(&adev_init_lock);
3642 return 0;
3643 }
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 adev = calloc(1, sizeof(struct audio_device));
3646
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003647 if (!adev) {
3648 pthread_mutex_unlock(&adev_init_lock);
3649 return -ENOMEM;
3650 }
3651
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003652 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3655 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3656 adev->device.common.module = (struct hw_module_t *)module;
3657 adev->device.common.close = adev_close;
3658
3659 adev->device.init_check = adev_init_check;
3660 adev->device.set_voice_volume = adev_set_voice_volume;
3661 adev->device.set_master_volume = adev_set_master_volume;
3662 adev->device.get_master_volume = adev_get_master_volume;
3663 adev->device.set_master_mute = adev_set_master_mute;
3664 adev->device.get_master_mute = adev_get_master_mute;
3665 adev->device.set_mode = adev_set_mode;
3666 adev->device.set_mic_mute = adev_set_mic_mute;
3667 adev->device.get_mic_mute = adev_get_mic_mute;
3668 adev->device.set_parameters = adev_set_parameters;
3669 adev->device.get_parameters = adev_get_parameters;
3670 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3671 adev->device.open_output_stream = adev_open_output_stream;
3672 adev->device.close_output_stream = adev_close_output_stream;
3673 adev->device.open_input_stream = adev_open_input_stream;
3674 adev->device.close_input_stream = adev_close_input_stream;
3675 adev->device.dump = adev_dump;
3676
3677 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003679 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003680 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003683 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003684 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003685 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003686 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003687 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003688 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003689 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303690 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303691
3692 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3693 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003695 adev->platform = platform_init(adev);
3696 if (!adev->platform) {
3697 free(adev->snd_dev_ref_cnt);
3698 free(adev);
3699 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3700 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003701 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003702 return -EINVAL;
3703 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003704
Naresh Tanniru4c630392014-05-12 01:05:52 +05303705 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3706
Eric Laurentc4aef752013-09-12 17:45:53 -07003707 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3708 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3709 if (adev->visualizer_lib == NULL) {
3710 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3711 } else {
3712 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3713 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003714 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003715 "visualizer_hal_start_output");
3716 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003717 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003718 "visualizer_hal_stop_output");
3719 }
3720 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003721 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003722 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003723
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003724 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3725 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3726 if (adev->offload_effects_lib == NULL) {
3727 ALOGE("%s: DLOPEN failed for %s", __func__,
3728 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3729 } else {
3730 ALOGV("%s: DLOPEN successful for %s", __func__,
3731 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3732 adev->offload_effects_start_output =
3733 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3734 "offload_effects_bundle_hal_start_output");
3735 adev->offload_effects_stop_output =
3736 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3737 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003738 adev->offload_effects_set_hpx_state =
3739 (int (*)(bool))dlsym(adev->offload_effects_lib,
3740 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003741 }
3742 }
3743
Mingming Yin514a8bc2014-07-29 15:22:21 -07003744 adev->bt_wb_speech_enabled = false;
3745
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003746 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 *device = &adev->device.common;
3748
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003749 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3750 &adev->streams_output_cfg_list);
3751
Kiran Kandi910e1862013-10-29 13:29:42 -07003752 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003753
3754 char value[PROPERTY_VALUE_MAX];
3755 int trial;
3756 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3757 trial = atoi(value);
3758 if (period_size_is_plausible_for_low_latency(trial)) {
3759 pcm_config_low_latency.period_size = trial;
3760 pcm_config_low_latency.start_threshold = trial / 4;
3761 pcm_config_low_latency.avail_min = trial / 4;
3762 configured_low_latency_capture_period_size = trial;
3763 }
3764 }
3765 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3766 trial = atoi(value);
3767 if (period_size_is_plausible_for_low_latency(trial)) {
3768 configured_low_latency_capture_period_size = trial;
3769 }
3770 }
3771
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003772 pthread_mutex_unlock(&adev_init_lock);
3773
Eric Laurent994a6932013-07-17 11:51:42 -07003774 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 return 0;
3776}
3777
3778static struct hw_module_methods_t hal_module_methods = {
3779 .open = adev_open,
3780};
3781
3782struct audio_module HAL_MODULE_INFO_SYM = {
3783 .common = {
3784 .tag = HARDWARE_MODULE_TAG,
3785 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3786 .hal_api_version = HARDWARE_HAL_API_VERSION,
3787 .id = AUDIO_HARDWARE_MODULE_ID,
3788 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003789 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 .methods = &hal_module_methods,
3791 },
3792};