blob: 5a2469aae9c7548eca7d3d4a3e89c36be99c385b [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
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -0700180 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
215#ifdef MULTIPLE_OFFLOAD_ENABLED
216 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
224#endif
225};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226
227#define STRING_TO_ENUM(string) { #string, string }
228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229struct string_to_enum {
230 const char *name;
231 uint32_t value;
232};
233
234static const struct string_to_enum out_channels_name_to_enum_table[] = {
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
242};
243
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700244static const struct string_to_enum out_formats_name_to_enum_table[] = {
245 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
247 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
248};
249
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700250static struct audio_device *adev = NULL;
251static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700252static unsigned int audio_device_ref_count;
253
Haynes Mathew George5191a852013-09-11 14:19:36 -0700254static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800256static int check_and_set_gapless_mode(struct audio_device *adev) {
257
258
259 char value[PROPERTY_VALUE_MAX] = {0};
260 bool gapless_enabled = false;
261 const char *mixer_ctl_name = "Compress Gapless Playback";
262 struct mixer_ctl *ctl;
263
264 ALOGV("%s:", __func__);
265 property_get("audio.offload.gapless.enabled", value, NULL);
266 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
267
268 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
269 if (!ctl) {
270 ALOGE("%s: Could not get ctl for mixer cmd - %s",
271 __func__, mixer_ctl_name);
272 return -EINVAL;
273 }
274
275 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
276 ALOGE("%s: Could not set gapless mode %d",
277 __func__, gapless_enabled);
278 return -EINVAL;
279 }
280 return 0;
281}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700283static bool is_supported_format(audio_format_t format)
284{
Eric Laurent86e17132013-09-12 17:49:30 -0700285 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530286 format == AUDIO_FORMAT_AAC_LC ||
287 format == AUDIO_FORMAT_AAC_HE_V1 ||
288 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangan93672f12015-08-24 20:30:31 +0530289 format == AUDIO_FORMAT_AAC_ADTS_LC ||
290 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
291 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800292 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700293 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530295 format == AUDIO_FORMAT_ALAC ||
296 format == AUDIO_FORMAT_APE ||
297 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800298 format == AUDIO_FORMAT_WMA ||
299 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800300 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301
302 return false;
303}
304
305static int get_snd_codec_id(audio_format_t format)
306{
307 int id = 0;
308
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700310 case AUDIO_FORMAT_MP3:
311 id = SND_AUDIOCODEC_MP3;
312 break;
313 case AUDIO_FORMAT_AAC:
314 id = SND_AUDIOCODEC_AAC;
315 break;
Manish Dewangan93672f12015-08-24 20:30:31 +0530316 case AUDIO_FORMAT_AAC_ADTS:
317 id = SND_AUDIOCODEC_AAC;
318 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530319 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800320 id = SND_AUDIOCODEC_PCM;
321 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700322 case AUDIO_FORMAT_FLAC:
323 id = SND_AUDIOCODEC_FLAC;
324 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530325 case AUDIO_FORMAT_ALAC:
326 id = SND_AUDIOCODEC_ALAC;
327 break;
328 case AUDIO_FORMAT_APE:
329 id = SND_AUDIOCODEC_APE;
330 break;
331 case AUDIO_FORMAT_VORBIS:
332 id = SND_AUDIOCODEC_VORBIS;
333 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800334 case AUDIO_FORMAT_WMA:
335 id = SND_AUDIOCODEC_WMA;
336 break;
337 case AUDIO_FORMAT_WMA_PRO:
338 id = SND_AUDIOCODEC_WMA_PRO;
339 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700340 default:
Mingming Yin90310102013-11-13 16:57:00 -0800341 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700342 }
343
344 return id;
345}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800346
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530347int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530348{
349 int snd_scard_state;
350
351 if (!adev)
352 return SND_CARD_STATE_OFFLINE;
353
354 pthread_mutex_lock(&adev->snd_card_status.lock);
355 snd_scard_state = adev->snd_card_status.state;
356 pthread_mutex_unlock(&adev->snd_card_status.lock);
357
358 return snd_scard_state;
359}
360
361static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
362{
363 if (!adev)
364 return -ENOSYS;
365
366 pthread_mutex_lock(&adev->snd_card_status.lock);
367 adev->snd_card_status.state = snd_scard_state;
368 pthread_mutex_unlock(&adev->snd_card_status.lock);
369
370 return 0;
371}
372
Avinash Vaish71a8b972014-07-24 15:36:33 +0530373static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
374 struct audio_usecase *uc_info)
375{
376 struct listnode *node;
377 struct audio_usecase *usecase;
378
379 if (uc_info == NULL)
380 return -EINVAL;
381
382 /* Re-route all voice usecases on the shared backend other than the
383 specified usecase to new snd devices */
384 list_for_each(node, &adev->usecase_list) {
385 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800386 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530387 enable_audio_route(adev, usecase);
388 }
389 return 0;
390}
391
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700392int pcm_ioctl(struct pcm *pcm, int request, ...)
393{
394 va_list ap;
395 void * arg;
396 int pcm_fd = *(int*)pcm;
397
398 va_start(ap, request);
399 arg = va_arg(ap, void *);
400 va_end(ap);
401
402 return ioctl(pcm_fd, request, arg);
403}
404
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700405int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700406 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700408 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700409 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800410
411 if (usecase == NULL)
412 return -EINVAL;
413
414 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
415
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800416 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700417 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800418 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700419 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800420
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800421#ifdef DS1_DOLBY_DAP_ENABLED
422 audio_extn_dolby_set_dmid(adev);
423 audio_extn_dolby_set_endpoint(adev);
424#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700425 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700426 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530427 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700428 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530429 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800430 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530431 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700432 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
433 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434 ALOGV("%s: exit", __func__);
435 return 0;
436}
437
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700438int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700439 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700442 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530444 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 return -EINVAL;
446
447 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700448 if (usecase->type == PCM_CAPTURE)
449 snd_device = usecase->in_snd_device;
450 else
451 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800452 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530453 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700454 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
455 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700456 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530457 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 ALOGV("%s: exit", __func__);
459 return 0;
460}
461
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700462int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700463 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700465 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
466
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800467 if (snd_device < SND_DEVICE_MIN ||
468 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800469 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472
473 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474
475 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
476 ALOGE("%s: Invalid sound device returned", __func__);
477 return -EINVAL;
478 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700479 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700480 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700482 return 0;
483 }
484
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700485 if (audio_extn_spkr_prot_is_enabled())
486 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700487 /* start usb playback thread */
488 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
489 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
490 audio_extn_usb_start_playback(adev);
491
492 /* start usb capture thread */
493 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
494 audio_extn_usb_start_capture(adev);
495
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530496 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530497 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700499 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700500 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
501 adev->snd_dev_ref_cnt[snd_device]--;
502 return -EINVAL;
503 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200504 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800505 if (audio_extn_spkr_prot_start_processing(snd_device)) {
506 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200507 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800508 return -EINVAL;
509 }
510 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700511 ALOGV("%s: snd_device(%d: %s)", __func__,
512 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700513 /* due to the possibility of calibration overwrite between listen
514 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700515 audio_extn_sound_trigger_update_device_status(snd_device,
516 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530517 audio_extn_listen_update_device_status(snd_device,
518 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700519 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700520 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700521 audio_extn_sound_trigger_update_device_status(snd_device,
522 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530523 audio_extn_listen_update_device_status(snd_device,
524 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700525 return -EINVAL;
526 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300527 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700528 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800530 return 0;
531}
532
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700533int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700534 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700536 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
537
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800538 if (snd_device < SND_DEVICE_MIN ||
539 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800540 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800541 return -EINVAL;
542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
544 ALOGE("%s: device ref cnt is already 0", __func__);
545 return -EINVAL;
546 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700549
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
551 ALOGE("%s: Invalid sound device returned", __func__);
552 return -EINVAL;
553 }
554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700555 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700556 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700557 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558 /* exit usb play back thread */
559 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
560 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
561 audio_extn_usb_stop_playback();
562
563 /* exit usb capture thread */
564 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700565 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800566
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530567 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530568 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800569 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700570 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700571 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300572 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700573 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300574 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700575
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530576 if (snd_device == SND_DEVICE_OUT_HDMI)
577 adev->mChannelStatusSet = false;
578
Linux Build Service Account75e43952015-08-26 19:58:56 -0700579 if (snd_device == SND_DEVICE_OUT_HDMI)
580 adev->mChannelStatusSet = false;
581
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200582 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700583 audio_extn_sound_trigger_update_device_status(snd_device,
584 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530585 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800586 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589 return 0;
590}
591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592static void check_usecases_codec_backend(struct audio_device *adev,
593 struct audio_usecase *uc_info,
594 snd_device_t snd_device)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598 bool switch_device[AUDIO_USECASE_MAX];
599 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530600 int backend_idx = DEFAULT_CODEC_BACKEND;
601 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602
603 /*
604 * This function is to make sure that all the usecases that are active on
605 * the hardware codec backend are always routed to any one device that is
606 * handled by the hardware codec.
607 * For example, if low-latency and deep-buffer usecases are currently active
608 * on speaker and out_set_parameters(headset) is received on low-latency
609 * output, then we have to make sure deep-buffer is also switched to headset,
610 * because of the limitation that both the devices cannot be enabled
611 * at the same time as they share the same backend.
612 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700613 /*
614 * This call is to check if we need to force routing for a particular stream
615 * If there is a backend configuration change for the device when a
616 * new stream starts, then ADM needs to be closed and re-opened with the new
617 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530618 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700619 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530620 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
621 snd_device);
622 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800624 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800625 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 for (i = 0; i < AUDIO_USECASE_MAX; i++)
627 switch_device[i] = false;
628
629 list_for_each(node, &adev->usecase_list) {
630 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530631
632 if (usecase == uc_info)
633 continue;
634 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
635 ALOGV("%s: backend_idx: %d,"
636 "usecase_backend_idx: %d, curr device: %s, usecase device:"
637 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530638 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530639
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800640 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700641 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530642 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
643 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530644 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530645 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700646 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700647 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 switch_device[usecase->id] = true;
649 num_uc_to_switch++;
650 }
651 }
652
653 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700654 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530656 /* Make sure the previous devices to be disabled first and then enable the
657 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -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 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 }
663 }
664
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
667 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700668 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700669 }
670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 /* Re-route all the usecases on the shared backend other than the
673 specified usecase to new snd devices */
674 list_for_each(node, &adev->usecase_list) {
675 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530676 /* Update the out_snd_device only before enabling the audio route */
677 if (switch_device[usecase->id] ) {
678 usecase->out_snd_device = snd_device;
679 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530680 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 }
682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 }
684}
685
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700686static void check_and_route_capture_usecases(struct audio_device *adev,
687 struct audio_usecase *uc_info,
688 snd_device_t snd_device)
689{
690 struct listnode *node;
691 struct audio_usecase *usecase;
692 bool switch_device[AUDIO_USECASE_MAX];
693 int i, num_uc_to_switch = 0;
694
695 /*
696 * This function is to make sure that all the active capture usecases
697 * are always routed to the same input sound device.
698 * For example, if audio-record and voice-call usecases are currently
699 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
700 * is received for voice call then we have to make sure that audio-record
701 * usecase is also switched to earpiece i.e. voice-dmic-ef,
702 * because of the limitation that two devices cannot be enabled
703 * at the same time if they share the same backend.
704 */
705 for (i = 0; i < AUDIO_USECASE_MAX; i++)
706 switch_device[i] = false;
707
708 list_for_each(node, &adev->usecase_list) {
709 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800710 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700712 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700713 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530714 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
715 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700716 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700717 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
718 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700719 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700720 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700721 switch_device[usecase->id] = true;
722 num_uc_to_switch++;
723 }
724 }
725
726 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700727 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530729 /* Make sure the previous devices to be disabled first and then enable the
730 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731 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 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800735 }
736 }
737
738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
740 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700741 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 }
743 }
744
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 /* Re-route all the usecases on the shared backend other than the
746 specified usecase to new snd devices */
747 list_for_each(node, &adev->usecase_list) {
748 usecase = node_to_item(node, struct audio_usecase, list);
749 /* Update the in_snd_device only before enabling the audio route */
750 if (switch_device[usecase->id] ) {
751 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800752 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530753 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 }
755 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 }
757}
758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700760static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800761{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700763 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764
765 switch (channels) {
766 /*
767 * Do not handle stereo output in Multi-channel cases
768 * Stereo case is handled in normal playback path
769 */
770 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700771 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777 break;
778 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700779 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786 break;
787 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700788 ALOGE("HDMI does not support multi channel playback");
789 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800790 break;
791 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700792 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793}
794
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800795audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
796 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700797{
798 struct audio_usecase *usecase;
799 struct listnode *node;
800
801 list_for_each(node, &adev->usecase_list) {
802 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800803 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700804 ALOGV("%s: usecase id %d", __func__, usecase->id);
805 return usecase->id;
806 }
807 }
808 return USECASE_INVALID;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700812 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700813{
814 struct audio_usecase *usecase;
815 struct listnode *node;
816
817 list_for_each(node, &adev->usecase_list) {
818 usecase = node_to_item(node, struct audio_usecase, list);
819 if (usecase->id == uc_id)
820 return usecase;
821 }
822 return NULL;
823}
824
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700825int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800827 snd_device_t out_snd_device = SND_DEVICE_NONE;
828 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829 struct audio_usecase *usecase = NULL;
830 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800831 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800832 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800833 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800834 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 usecase = get_usecase_from_list(adev, uc_id);
838 if (usecase == NULL) {
839 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
840 return -EINVAL;
841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800843 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800844 (usecase->type == VOIP_CALL) ||
845 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700846 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800847 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700848 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 usecase->devices = usecase->stream.out->devices;
850 } else {
851 /*
852 * If the voice call is active, use the sound devices of voice call usecase
853 * so that it would not result any device switch. All the usecases will
854 * be switched to new device when select_devices() is called for voice call
855 * usecase. This is to avoid switching devices for voice call when
856 * check_usecases_codec_backend() is called below.
857 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700858 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700859 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800860 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700861 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
862 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 in_snd_device = vc_usecase->in_snd_device;
864 out_snd_device = vc_usecase->out_snd_device;
865 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800866 } else if (voice_extn_compress_voip_is_active(adev)) {
867 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530869 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700870 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800871 in_snd_device = voip_usecase->in_snd_device;
872 out_snd_device = voip_usecase->out_snd_device;
873 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800874 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800875 hfp_ucid = audio_extn_hfp_get_usecase();
876 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700877 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800878 in_snd_device = hfp_usecase->in_snd_device;
879 out_snd_device = hfp_usecase->out_snd_device;
880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 if (usecase->type == PCM_PLAYBACK) {
883 usecase->devices = usecase->stream.out->devices;
884 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700885 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700886 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800887 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700888 if (usecase->stream.out == adev->primary_output &&
889 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800890 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 select_devices(adev, adev->active_input->usecase);
892 }
893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 } else if (usecase->type == PCM_CAPTURE) {
895 usecase->devices = usecase->stream.in->device;
896 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700898 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530899 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
900 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
901 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
902 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700903 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -0700904 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700905 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
906 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700907 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700908 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 }
911 }
912
913 if (out_snd_device == usecase->out_snd_device &&
914 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915 return 0;
916 }
917
sangwoobc677242013-08-08 16:53:43 +0900918 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700919 out_snd_device, platform_get_snd_device_name(out_snd_device),
920 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 /*
923 * Limitation: While in call, to do a device switch we need to disable
924 * and enable both RX and TX devices though one of them is same as current
925 * device.
926 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700927 if ((usecase->type == VOICE_CALL) &&
928 (usecase->in_snd_device != SND_DEVICE_NONE) &&
929 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700930 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700931 }
932
933 if (((usecase->type == VOICE_CALL) ||
934 (usecase->type == VOIP_CALL)) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
936 /* Disable sidetone only if voice/voip call already exists */
937 if (voice_is_call_state_active(adev) ||
938 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700939 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800940 }
941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Disable current sound devices */
943 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700944 disable_audio_route(adev, usecase);
945 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 disable_audio_route(adev, usecase);
950 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951 }
952
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800953 /* Applicable only on the targets that has external modem.
954 * New device information should be sent to modem before enabling
955 * the devices to reduce in-call device switch time.
956 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700957 if ((usecase->type == VOICE_CALL) &&
958 (usecase->in_snd_device != SND_DEVICE_NONE) &&
959 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800960 status = platform_switch_voice_call_enable_device_config(adev->platform,
961 out_snd_device,
962 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800964
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700965 /* Enable new sound devices */
966 if (out_snd_device != SND_DEVICE_NONE) {
967 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
968 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970 }
971
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700972 if (in_snd_device != SND_DEVICE_NONE) {
973 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976
Avinash Vaish71a8b972014-07-24 15:36:33 +0530977 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700978 status = platform_switch_voice_call_device_post(adev->platform,
979 out_snd_device,
980 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530981 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700982 /* Enable sidetone only if voice/voip call already exists */
983 if (voice_is_call_state_active(adev) ||
984 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700985 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530986 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800987
sangwoo170731f2013-06-08 15:36:36 +0900988 usecase->in_snd_device = in_snd_device;
989 usecase->out_snd_device = out_snd_device;
990
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530991 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700992 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530993 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700994 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530995 usecase->stream.out->flags,
996 usecase->stream.out->format,
997 usecase->stream.out->sample_rate,
998 usecase->stream.out->bit_width,
999 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001002
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001003 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001004
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001005 /* Applicable only on the targets that has external modem.
1006 * Enable device command should be sent to modem only after
1007 * enabling voice call mixer controls
1008 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001009 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001010 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1011 out_snd_device,
1012 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301013 ALOGD("%s: done",__func__);
1014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 return status;
1016}
1017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018static int stop_input_stream(struct stream_in *in)
1019{
1020 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 struct audio_usecase *uc_info;
1022 struct audio_device *adev = in->dev;
1023
Eric Laurentc8400632013-02-14 19:04:54 -08001024 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Eric Laurent994a6932013-07-17 11:51:42 -07001026 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 uc_info = get_usecase_from_list(adev, in->usecase);
1029 if (uc_info == NULL) {
1030 ALOGE("%s: Could not find the usecase (%d) in the list",
1031 __func__, in->usecase);
1032 return -EINVAL;
1033 }
1034
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001035 /* Close in-call recording streams */
1036 voice_check_and_stop_incall_rec_usecase(adev, in);
1037
Eric Laurent150dbfe2013-02-27 14:31:02 -08001038 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001039 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040
1041 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001044 list_remove(&uc_info->list);
1045 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 return ret;
1049}
1050
1051int start_input_stream(struct stream_in *in)
1052{
1053 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001054 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 struct audio_usecase *uc_info;
1056 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301057 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301059 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1060 if (get_usecase_from_list(adev, usecase) == NULL)
1061 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301062 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1063 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001064
Naresh Tanniru80659832014-06-04 18:17:56 +05301065
1066 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301067 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301068 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301069 goto error_config;
1070 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301071
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001072 /* Check if source matches incall recording usecase criteria */
1073 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1074 if (ret)
1075 goto error_config;
1076 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301077 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1078
1079 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1080 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1081 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1082 goto error_config;
1083 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084
Eric Laurentb23d5282013-05-14 15:27:20 -07001085 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 if (in->pcm_device_id < 0) {
1087 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1088 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001089 ret = -EINVAL;
1090 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092
1093 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001095
1096 if (!uc_info) {
1097 ret = -ENOMEM;
1098 goto error_config;
1099 }
1100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 uc_info->id = in->usecase;
1102 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001103 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 uc_info->devices = in->device;
1105 uc_info->in_snd_device = SND_DEVICE_NONE;
1106 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001108 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301109 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111
Eric Laurentc8400632013-02-14 19:04:54 -08001112 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001113 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1114
1115 unsigned int flags = PCM_IN;
1116 unsigned int pcm_open_retry_count = 0;
1117
1118 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1119 flags |= PCM_MMAP | PCM_NOIRQ;
1120 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1121 }
1122
1123 while (1) {
1124 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1125 flags, &in->config);
1126 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1127 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1128 if (in->pcm != NULL) {
1129 pcm_close(in->pcm);
1130 in->pcm = NULL;
1131 }
1132 if (pcm_open_retry_count-- == 0) {
1133 ret = -EIO;
1134 goto error_open;
1135 }
1136 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1137 continue;
1138 }
1139 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301141 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301142
Eric Laurent994a6932013-07-17 11:51:42 -07001143 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001144 return ret;
1145
1146error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301148 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001149
1150error_config:
1151 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001153
1154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155}
1156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001157/* must be called with out->lock locked */
1158static int send_offload_cmd_l(struct stream_out* out, int command)
1159{
1160 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1161
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001162 if (!cmd) {
1163 ALOGE("failed to allocate mem for command 0x%x", command);
1164 return -ENOMEM;
1165 }
1166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001167 ALOGVV("%s %d", __func__, command);
1168
1169 cmd->cmd = command;
1170 list_add_tail(&out->offload_cmd_list, &cmd->node);
1171 pthread_cond_signal(&out->offload_cond);
1172 return 0;
1173}
1174
1175/* must be called iwth out->lock locked */
1176static void stop_compressed_output_l(struct stream_out *out)
1177{
1178 out->offload_state = OFFLOAD_STATE_IDLE;
1179 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001180 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001181 if (out->compr != NULL) {
1182 compress_stop(out->compr);
1183 while (out->offload_thread_blocked) {
1184 pthread_cond_wait(&out->cond, &out->lock);
1185 }
1186 }
1187}
1188
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001189bool is_offload_usecase(audio_usecase_t uc_id)
1190{
1191 unsigned int i;
1192 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1193 if (uc_id == offload_usecases[i])
1194 return true;
1195 }
1196 return false;
1197}
1198
1199static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1200{
1201 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1202 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1203 char value[PROPERTY_VALUE_MAX] = {0};
1204
1205 property_get("audio.offload.multiple.enabled", value, NULL);
1206 if (!(atoi(value) || !strncmp("true", value, 4)))
1207 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1208
1209 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1210 for (i = 0; i < num_usecase; i++) {
1211 if (!(adev->offload_usecases_state & (0x1<<i))) {
1212 adev->offload_usecases_state |= 0x1 << i;
1213 ret = offload_usecases[i];
1214 break;
1215 }
1216 }
1217 ALOGV("%s: offload usecase is %d", __func__, ret);
1218 return ret;
1219}
1220
1221static void free_offload_usecase(struct audio_device *adev,
1222 audio_usecase_t uc_id)
1223{
1224 unsigned int i;
1225 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1226 if (offload_usecases[i] == uc_id) {
1227 adev->offload_usecases_state &= ~(0x1<<i);
1228 break;
1229 }
1230 }
1231 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1232}
1233
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001234static void *offload_thread_loop(void *context)
1235{
1236 struct stream_out *out = (struct stream_out *) context;
1237 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001238 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1241 set_sched_policy(0, SP_FOREGROUND);
1242 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1243
1244 ALOGV("%s", __func__);
1245 pthread_mutex_lock(&out->lock);
1246 for (;;) {
1247 struct offload_cmd *cmd = NULL;
1248 stream_callback_event_t event;
1249 bool send_callback = false;
1250
1251 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1252 __func__, list_empty(&out->offload_cmd_list),
1253 out->offload_state);
1254 if (list_empty(&out->offload_cmd_list)) {
1255 ALOGV("%s SLEEPING", __func__);
1256 pthread_cond_wait(&out->offload_cond, &out->lock);
1257 ALOGV("%s RUNNING", __func__);
1258 continue;
1259 }
1260
1261 item = list_head(&out->offload_cmd_list);
1262 cmd = node_to_item(item, struct offload_cmd, node);
1263 list_remove(item);
1264
1265 ALOGVV("%s STATE %d CMD %d out->compr %p",
1266 __func__, out->offload_state, cmd->cmd, out->compr);
1267
1268 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1269 free(cmd);
1270 break;
1271 }
1272
1273 if (out->compr == NULL) {
1274 ALOGE("%s: Compress handle is NULL", __func__);
1275 pthread_cond_signal(&out->cond);
1276 continue;
1277 }
1278 out->offload_thread_blocked = true;
1279 pthread_mutex_unlock(&out->lock);
1280 send_callback = false;
1281 switch(cmd->cmd) {
1282 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001283 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001286 send_callback = true;
1287 event = STREAM_CBK_EVENT_WRITE_READY;
1288 break;
1289 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001290 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301291 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001292 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301293 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001294 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301295 if (ret < 0)
1296 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301297 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301298 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001299 compress_drain(out->compr);
1300 else
1301 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301302 if (ret != -ENETRESET) {
1303 send_callback = true;
1304 event = STREAM_CBK_EVENT_DRAIN_READY;
1305 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1306 } else
1307 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001308 break;
1309 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001310 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001311 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001312 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 send_callback = true;
1314 event = STREAM_CBK_EVENT_DRAIN_READY;
1315 break;
1316 default:
1317 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1318 break;
1319 }
1320 pthread_mutex_lock(&out->lock);
1321 out->offload_thread_blocked = false;
1322 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001323 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001324 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001325 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001326 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001327 free(cmd);
1328 }
1329
1330 pthread_cond_signal(&out->cond);
1331 while (!list_empty(&out->offload_cmd_list)) {
1332 item = list_head(&out->offload_cmd_list);
1333 list_remove(item);
1334 free(node_to_item(item, struct offload_cmd, node));
1335 }
1336 pthread_mutex_unlock(&out->lock);
1337
1338 return NULL;
1339}
1340
1341static int create_offload_callback_thread(struct stream_out *out)
1342{
1343 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1344 list_init(&out->offload_cmd_list);
1345 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1346 offload_thread_loop, out);
1347 return 0;
1348}
1349
1350static int destroy_offload_callback_thread(struct stream_out *out)
1351{
1352 pthread_mutex_lock(&out->lock);
1353 stop_compressed_output_l(out);
1354 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1355
1356 pthread_mutex_unlock(&out->lock);
1357 pthread_join(out->offload_thread, (void **) NULL);
1358 pthread_cond_destroy(&out->offload_cond);
1359
1360 return 0;
1361}
1362
Eric Laurent07eeafd2013-10-06 12:52:49 -07001363static bool allow_hdmi_channel_config(struct audio_device *adev)
1364{
1365 struct listnode *node;
1366 struct audio_usecase *usecase;
1367 bool ret = true;
1368
1369 list_for_each(node, &adev->usecase_list) {
1370 usecase = node_to_item(node, struct audio_usecase, list);
1371 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1372 /*
1373 * If voice call is already existing, do not proceed further to avoid
1374 * disabling/enabling both RX and TX devices, CSD calls, etc.
1375 * Once the voice call done, the HDMI channels can be configured to
1376 * max channels of remaining use cases.
1377 */
1378 if (usecase->id == USECASE_VOICE_CALL) {
1379 ALOGD("%s: voice call is active, no change in HDMI channels",
1380 __func__);
1381 ret = false;
1382 break;
1383 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1384 ALOGD("%s: multi channel playback is active, "
1385 "no change in HDMI channels", __func__);
1386 ret = false;
1387 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001388 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001389 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001390 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1391 ", no change in HDMI channels", __func__,
1392 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001393 ret = false;
1394 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001395 }
1396 }
1397 }
1398 return ret;
1399}
1400
1401static int check_and_set_hdmi_channels(struct audio_device *adev,
1402 unsigned int channels)
1403{
1404 struct listnode *node;
1405 struct audio_usecase *usecase;
1406
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001407 unsigned int supported_channels = platform_edid_get_max_channels(
1408 adev->platform);
1409 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001410 /* Check if change in HDMI channel config is allowed */
1411 if (!allow_hdmi_channel_config(adev))
1412 return 0;
1413
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001414 if (channels > supported_channels)
1415 channels = supported_channels;
1416
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001418 ALOGD("%s: Requested channels are same as current channels(%d)",
1419 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 return 0;
1421 }
1422
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001423 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001424 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001425 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001426 adev->cur_hdmi_channels = channels;
1427
1428 /*
1429 * Deroute all the playback streams routed to HDMI so that
1430 * the back end is deactivated. Note that backend will not
1431 * be deactivated if any one stream is connected to it.
1432 */
1433 list_for_each(node, &adev->usecase_list) {
1434 usecase = node_to_item(node, struct audio_usecase, list);
1435 if (usecase->type == PCM_PLAYBACK &&
1436 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001437 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001438 }
1439 }
1440
1441 /*
1442 * Enable all the streams disabled above. Now the HDMI backend
1443 * will be activated with new channel configuration
1444 */
1445 list_for_each(node, &adev->usecase_list) {
1446 usecase = node_to_item(node, struct audio_usecase, list);
1447 if (usecase->type == PCM_PLAYBACK &&
1448 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001449 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001450 }
1451 }
1452
1453 return 0;
1454}
1455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456static int stop_output_stream(struct stream_out *out)
1457{
1458 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 struct audio_usecase *uc_info;
1460 struct audio_device *adev = out->dev;
1461
Eric Laurent994a6932013-07-17 11:51:42 -07001462 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 uc_info = get_usecase_from_list(adev, out->usecase);
1465 if (uc_info == NULL) {
1466 ALOGE("%s: Could not find the usecase (%d) in the list",
1467 __func__, out->usecase);
1468 return -EINVAL;
1469 }
1470
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001471 if (is_offload_usecase(out->usecase) &&
1472 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001473 if (adev->visualizer_stop_output != NULL)
1474 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001475
1476 audio_extn_dts_remove_state_notifier_node(out->usecase);
1477
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001478 if (adev->offload_effects_stop_output != NULL)
1479 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1480 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001481
Eric Laurent150dbfe2013-02-27 14:31:02 -08001482 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001483 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484
1485 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001486 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001488 list_remove(&uc_info->list);
1489 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001491 if (is_offload_usecase(out->usecase) &&
1492 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1493 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1494 ALOGV("Disable passthrough , reset mixer to pcm");
1495 /* NO_PASSTHROUGH */
1496 out->compr_config.codec->compr_passthr = 0;
1497 audio_extn_dolby_set_hdmi_config(adev, out);
1498 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1499 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001500 /* Must be called after removing the usecase from list */
1501 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1502 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1503
Eric Laurent994a6932013-07-17 11:51:42 -07001504 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 return ret;
1506}
1507
1508int start_output_stream(struct stream_out *out)
1509{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001511 int sink_channels = 0;
1512 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 struct audio_usecase *uc_info;
1514 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301515 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001517 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1518 ret = -EINVAL;
1519 goto error_config;
1520 }
1521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301522 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1523 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1524 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301525
Naresh Tanniru80659832014-06-04 18:17:56 +05301526 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301527 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301528 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301529 goto error_config;
1530 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301531
Eric Laurentb23d5282013-05-14 15:27:20 -07001532 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 if (out->pcm_device_id < 0) {
1534 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1535 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001536 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001537 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 }
1539
1540 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001541
1542 if (!uc_info) {
1543 ret = -ENOMEM;
1544 goto error_config;
1545 }
1546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 uc_info->id = out->usecase;
1548 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001549 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001550 uc_info->devices = out->devices;
1551 uc_info->in_snd_device = SND_DEVICE_NONE;
1552 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001553 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001554 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001555 if (is_offload_usecase(out->usecase)) {
1556 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001557 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1558 }
1559 }
Mingming Yin9c041392014-05-01 15:37:31 -07001560 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1561 if (!strncmp("true", prop_value, 4)) {
1562 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001563 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1564 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001565 check_and_set_hdmi_channels(adev, sink_channels);
1566 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001567 if (is_offload_usecase(out->usecase)) {
1568 unsigned int ch_count = out->compr_config.codec->ch_in;
1569 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1570 /* backend channel config for passthrough stream is stereo */
1571 ch_count = 2;
1572 check_and_set_hdmi_channels(adev, ch_count);
1573 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001574 check_and_set_hdmi_channels(adev, out->config.channels);
1575 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001576 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001577 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001578 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 select_devices(adev, out->usecase);
1581
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001582 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1583 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001584 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001585 unsigned int flags = PCM_OUT;
1586 unsigned int pcm_open_retry_count = 0;
1587 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1588 flags |= PCM_MMAP | PCM_NOIRQ;
1589 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1590 } else
1591 flags |= PCM_MONOTONIC;
1592
1593 while (1) {
1594 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1595 flags, &out->config);
1596 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1597 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1598 if (out->pcm != NULL) {
1599 pcm_close(out->pcm);
1600 out->pcm = NULL;
1601 }
1602 if (pcm_open_retry_count-- == 0) {
1603 ret = -EIO;
1604 goto error_open;
1605 }
1606 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1607 continue;
1608 }
1609 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001610 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001611 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1612 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001613 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001614 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1615 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001617 out->compr = compress_open(adev->snd_card,
1618 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001619 COMPRESS_IN, &out->compr_config);
1620 if (out->compr && !is_compress_ready(out->compr)) {
1621 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1622 compress_close(out->compr);
1623 out->compr = NULL;
1624 ret = -EIO;
1625 goto error_open;
1626 }
1627 if (out->offload_callback)
1628 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001629
Fred Oh3f43e742015-03-04 18:42:34 -08001630 /* Since small bufs uses blocking writes, a write will be blocked
1631 for the default max poll time (20s) in the event of an SSR.
1632 Reduce the poll time to observe and deal with SSR faster.
1633 */
1634 if (out->use_small_bufs) {
1635 compress_set_max_poll_wait(out->compr, 1000);
1636 }
1637
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001638 audio_extn_dts_create_state_notifier_node(out->usecase);
1639 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1640 popcount(out->channel_mask),
1641 out->playback_started);
1642
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001643#ifdef DS1_DOLBY_DDP_ENABLED
1644 if (audio_extn_is_dolby_format(out->format))
1645 audio_extn_dolby_send_ddp_endp_params(adev);
1646#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001647 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1648 if (adev->visualizer_start_output != NULL)
1649 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1650 if (adev->offload_effects_start_output != NULL)
1651 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001652 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 }
Eric Laurent994a6932013-07-17 11:51:42 -07001655 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001659error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661}
1662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663static int check_input_parameters(uint32_t sample_rate,
1664 audio_format_t format,
1665 int channel_count)
1666{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001667 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001669 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001670 !voice_extn_compress_voip_is_format_supported(format) &&
1671 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001672
1673 switch (channel_count) {
1674 case 1:
1675 case 2:
1676 case 6:
1677 break;
1678 default:
1679 ret = -EINVAL;
1680 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681
1682 switch (sample_rate) {
1683 case 8000:
1684 case 11025:
1685 case 12000:
1686 case 16000:
1687 case 22050:
1688 case 24000:
1689 case 32000:
1690 case 44100:
1691 case 48000:
1692 break;
1693 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001694 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 }
1696
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001697 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698}
1699
1700static size_t get_input_buffer_size(uint32_t sample_rate,
1701 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001702 int channel_count,
1703 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704{
1705 size_t size = 0;
1706
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001707 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1708 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001710 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001711 if (is_low_latency)
1712 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001713 /* ToDo: should use frame_size computed based on the format and
1714 channel_count here. */
1715 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001717 /* make sure the size is multiple of 32 bytes
1718 * At 48 kHz mono 16-bit PCM:
1719 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1720 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1721 */
1722 size += 0x1f;
1723 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001724
1725 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
1728static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1729{
1730 struct stream_out *out = (struct stream_out *)stream;
1731
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733}
1734
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001735static int out_set_sample_rate(struct audio_stream *stream __unused,
1736 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737{
1738 return -ENOSYS;
1739}
1740
1741static size_t out_get_buffer_size(const struct audio_stream *stream)
1742{
1743 struct stream_out *out = (struct stream_out *)stream;
1744
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001745 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001747 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1748 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001749
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001750 return out->config.period_size *
1751 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752}
1753
1754static uint32_t out_get_channels(const struct audio_stream *stream)
1755{
1756 struct stream_out *out = (struct stream_out *)stream;
1757
1758 return out->channel_mask;
1759}
1760
1761static audio_format_t out_get_format(const struct audio_stream *stream)
1762{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 struct stream_out *out = (struct stream_out *)stream;
1764
1765 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766}
1767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001768static int out_set_format(struct audio_stream *stream __unused,
1769 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770{
1771 return -ENOSYS;
1772}
1773
1774static int out_standby(struct audio_stream *stream)
1775{
1776 struct stream_out *out = (struct stream_out *)stream;
1777 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301779 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1780 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001781 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1782 /* Ignore standby in case of voip call because the voip output
1783 * stream is closed in adev_close_output_stream()
1784 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301785 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001786 return 0;
1787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001791 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001793 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 if (out->pcm) {
1795 pcm_close(out->pcm);
1796 out->pcm = NULL;
1797 }
1798 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001799 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001801 out->gapless_mdata.encoder_delay = 0;
1802 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 if (out->compr != NULL) {
1804 compress_close(out->compr);
1805 out->compr = NULL;
1806 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001809 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 }
1811 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001812 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 return 0;
1814}
1815
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001816static int out_dump(const struct audio_stream *stream __unused,
1817 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818{
1819 return 0;
1820}
1821
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1823{
1824 int ret = 0;
1825 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301826 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001827
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001828 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001829 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 return -EINVAL;
1831 }
1832
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301833 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001834
Yadav Anamikafbcef792015-08-19 16:15:00 +05301835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1836 if(ret >= 0)
1837 is_meta_data_params = true;
1838 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1839 if(ret >= 0)
1840 is_meta_data_params = true;
1841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1842 if(ret >= 0)
1843 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1845 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301846 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301847 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1850 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301851 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301852 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853 }
1854
Yadav Anamikafbcef792015-08-19 16:15:00 +05301855 if(!is_meta_data_params) {
1856 ALOGV("%s: Not gapless meta data params", __func__);
1857 return 0;
1858 }
1859 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 ALOGV("%s new encoder delay %u and padding %u", __func__,
1861 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1862
1863 return 0;
1864}
1865
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001866static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1867{
1868 return out == adev->primary_output || out == adev->voice_tx_output;
1869}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1872{
1873 struct stream_out *out = (struct stream_out *)stream;
1874 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 struct audio_usecase *usecase;
1876 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 struct str_parms *parms;
1878 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001879 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001880 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881
sangwoobc677242013-08-08 16:53:43 +09001882 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301885 if (!parms)
1886 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001887 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1888 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001891 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001893 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301894 * When HDMI cable is unplugged/usb hs is disconnected the
1895 * music playback is paused and the policy manager sends routing=0
1896 * But the audioflingercontinues to write data until standby time
1897 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 * Avoid this by routing audio to speaker until standby.
1899 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301900 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1901 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001903 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1904 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 }
1906
1907 /*
1908 * select_devices() call below switches all the usecases on the same
1909 * backend to the new device. Refer to check_usecases_codec_backend() in
1910 * the select_devices(). But how do we undo this?
1911 *
1912 * For example, music playback is active on headset (deep-buffer usecase)
1913 * and if we go to ringtones and select a ringtone, low-latency usecase
1914 * will be started on headset+speaker. As we can't enable headset+speaker
1915 * and headset devices at the same time, select_devices() switches the music
1916 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1917 * So when the ringtone playback is completed, how do we undo the same?
1918 *
1919 * We are relying on the out_set_parameters() call on deep-buffer output,
1920 * once the ringtone playback is ended.
1921 * NOTE: We should not check if the current devices are same as new devices.
1922 * Because select_devices() must be called to switch back the music
1923 * playback to headset.
1924 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001925 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 out->devices = val;
1927
1928 if (!out->standby)
1929 select_devices(adev, out->usecase);
1930
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001931 if (output_drives_call(adev, out)) {
1932 if(!voice_is_in_call(adev)) {
1933 if (adev->mode == AUDIO_MODE_IN_CALL) {
1934 adev->current_call_output = out;
1935 ret = voice_start_call(adev);
1936 }
1937 } else {
1938 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001939 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001940 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001941 }
1942 }
1943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001945 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001947
1948 if (out == adev->primary_output) {
1949 pthread_mutex_lock(&adev->lock);
1950 audio_extn_set_parameters(adev, parms);
1951 pthread_mutex_unlock(&adev->lock);
1952 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001953 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001954 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001955 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001956
1957 audio_extn_dts_create_state_notifier_node(out->usecase);
1958 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1959 popcount(out->channel_mask),
1960 out->playback_started);
1961
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001962 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001963 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301966error:
Eric Laurent994a6932013-07-17 11:51:42 -07001967 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 return ret;
1969}
1970
1971static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1972{
1973 struct stream_out *out = (struct stream_out *)stream;
1974 struct str_parms *query = str_parms_create_str(keys);
1975 char *str;
1976 char value[256];
1977 struct str_parms *reply = str_parms_create();
1978 size_t i, j;
1979 int ret;
1980 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001981
1982 if (!query || !reply) {
1983 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1984 return NULL;
1985 }
1986
Eric Laurent994a6932013-07-17 11:51:42 -07001987 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1989 if (ret >= 0) {
1990 value[0] = '\0';
1991 i = 0;
1992 while (out->supported_channel_masks[i] != 0) {
1993 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1994 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1995 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001996 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001998 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 first = false;
2000 break;
2001 }
2002 }
2003 i++;
2004 }
2005 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2006 str = str_parms_to_str(reply);
2007 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002008 voice_extn_out_get_parameters(out, query, reply);
2009 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002010 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002011 free(str);
2012 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002013 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002015
2016 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2017 if (ret >= 0) {
2018 value[0] = '\0';
2019 i = 0;
2020 first = true;
2021 while (out->supported_formats[i] != 0) {
2022 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2023 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2024 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002025 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002026 }
2027 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2028 first = false;
2029 break;
2030 }
2031 }
2032 i++;
2033 }
2034 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2035 str = str_parms_to_str(reply);
2036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 str_parms_destroy(query);
2038 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002039 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 return str;
2041}
2042
2043static uint32_t out_get_latency(const struct audio_stream_out *stream)
2044{
2045 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002046 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Alexy Josephaa54c872014-12-03 02:46:47 -08002048 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002049 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002050 } else {
2051 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002053 }
2054
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302055 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002056 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057}
2058
2059static int out_set_volume(struct audio_stream_out *stream, float left,
2060 float right)
2061{
Eric Laurenta9024de2013-04-04 09:19:12 -07002062 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 int volume[2];
2064
Eric Laurenta9024de2013-04-04 09:19:12 -07002065 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2066 /* only take left channel into account: the API is for stereo anyway */
2067 out->muted = (left == 0.0f);
2068 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002069 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002070 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2071 /*
2072 * Set mute or umute on HDMI passthrough stream.
2073 * Only take left channel into account.
2074 * Mute is 0 and unmute 1
2075 */
2076 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2077 } else {
2078 char mixer_ctl_name[128];
2079 struct audio_device *adev = out->dev;
2080 struct mixer_ctl *ctl;
2081 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002082 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002084 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2085 "Compress Playback %d Volume", pcm_device_id);
2086 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2087 if (!ctl) {
2088 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2089 __func__, mixer_ctl_name);
2090 return -EINVAL;
2091 }
2092 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2093 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2094 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2095 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002097 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 return -ENOSYS;
2100}
2101
2102static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2103 size_t bytes)
2104{
2105 struct stream_out *out = (struct stream_out *)stream;
2106 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302107 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002108 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302111
Naresh Tanniru80659832014-06-04 18:17:56 +05302112 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002113 // increase written size during SSR to avoid mismatch
2114 // with the written frames count in AF
2115 if (!is_offload_usecase(out->usecase))
2116 out->written += bytes / (out->config.channels * sizeof(short));
2117
Naresh Tanniru80659832014-06-04 18:17:56 +05302118 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302119 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302120 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302121 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002122 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302123 //during SSR for compress usecase we should return error to flinger
2124 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2125 pthread_mutex_unlock(&out->lock);
2126 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 }
2128 }
2129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002131 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002132 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002133 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2134 ret = voice_extn_compress_voip_start_output_stream(out);
2135 else
2136 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002137 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002140 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 goto exit;
2142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302145 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2146 setChannelStatus(out, buffer, bytes);
2147 adev->mChannelStatusSet = true;
2148 }
2149
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002150 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002151 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002153 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2155 out->send_new_metadata = 0;
2156 }
2157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302159 if (ret < 0)
2160 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002161 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002162 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302163 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 } else if (-ENETRESET == ret) {
2166 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2167 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2168 pthread_mutex_unlock(&out->lock);
2169 out_standby(&out->stream.common);
2170 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302172 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002174 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 out->playback_started = 1;
2176 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002177
2178 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2179 popcount(out->channel_mask),
2180 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
2182 pthread_mutex_unlock(&out->lock);
2183 return ret;
2184 } else {
2185 if (out->pcm) {
2186 if (out->muted)
2187 memset((void *)buffer, 0, bytes);
2188 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002189 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2190 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2191 else
2192 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302193 if (ret < 0)
2194 ret = -errno;
2195 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002196 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 }
2199
2200exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302201 /* ToDo: There may be a corner case when SSR happens back to back during
2202 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302203 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205 }
2206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 pthread_mutex_unlock(&out->lock);
2208
2209 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002210 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002211 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302212 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302213 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302214 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302215 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302216 out->standby = true;
2217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002219 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 out_get_sample_rate(&out->stream.common));
2221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 }
2223 return bytes;
2224}
2225
2226static int out_get_render_position(const struct audio_stream_out *stream,
2227 uint32_t *dsp_frames)
2228{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302230 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002231
2232 if (dsp_frames == NULL)
2233 return -EINVAL;
2234
2235 *dsp_frames = 0;
2236 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002237 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 pthread_mutex_lock(&out->lock);
2239 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302240 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302242 if (ret < 0)
2243 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 ALOGVV("%s rendered frames %d sample_rate %d",
2245 __func__, *dsp_frames, out->sample_rate);
2246 }
2247 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302248 if (-ENETRESET == ret) {
2249 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2250 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2251 return -EINVAL;
2252 } else if(ret < 0) {
2253 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2254 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302255 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2256 /*
2257 * Handle corner case where compress session is closed during SSR
2258 * and timestamp is queried
2259 */
2260 ALOGE(" ERROR: sound card not active, return error");
2261 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302262 } else {
2263 return 0;
2264 }
Zhou Song32a556e2015-05-05 10:46:56 +08002265 } else if (audio_is_linear_pcm(out->format)) {
2266 *dsp_frames = out->written;
2267 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 } else
2269 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270}
2271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002272static int out_add_audio_effect(const struct audio_stream *stream __unused,
2273 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274{
2275 return 0;
2276}
2277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002278static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2279 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280{
2281 return 0;
2282}
2283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002284static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2285 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286{
2287 return -EINVAL;
2288}
2289
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002290static int out_get_presentation_position(const struct audio_stream_out *stream,
2291 uint64_t *frames, struct timespec *timestamp)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002296
2297 pthread_mutex_lock(&out->lock);
2298
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002299 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002300 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302301 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002302 &out->sample_rate);
2303 ALOGVV("%s rendered frames %ld sample_rate %d",
2304 __func__, dsp_frames, out->sample_rate);
2305 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302306 if (ret < 0)
2307 ret = -errno;
2308 if (-ENETRESET == ret) {
2309 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2310 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2311 ret = -EINVAL;
2312 } else
2313 ret = 0;
2314
Eric Laurent949a0892013-09-20 09:20:13 -07002315 /* this is the best we can do */
2316 clock_gettime(CLOCK_MONOTONIC, timestamp);
2317 }
2318 } else {
2319 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002321 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2322 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002323 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002324 // This adjustment accounts for buffering after app processor.
2325 // It is based on estimated DSP latency per use case, rather than exact.
2326 signed_frames -=
2327 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2328
Eric Laurent949a0892013-09-20 09:20:13 -07002329 // It would be unusual for this value to be negative, but check just in case ...
2330 if (signed_frames >= 0) {
2331 *frames = signed_frames;
2332 ret = 0;
2333 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002334 }
2335 }
2336 }
2337
2338 pthread_mutex_unlock(&out->lock);
2339
2340 return ret;
2341}
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343static int out_set_callback(struct audio_stream_out *stream,
2344 stream_callback_t callback, void *cookie)
2345{
2346 struct stream_out *out = (struct stream_out *)stream;
2347
2348 ALOGV("%s", __func__);
2349 pthread_mutex_lock(&out->lock);
2350 out->offload_callback = callback;
2351 out->offload_cookie = cookie;
2352 pthread_mutex_unlock(&out->lock);
2353 return 0;
2354}
2355
2356static int out_pause(struct audio_stream_out* stream)
2357{
2358 struct stream_out *out = (struct stream_out *)stream;
2359 int status = -ENOSYS;
2360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002362 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 pthread_mutex_lock(&out->lock);
2364 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302365 struct audio_device *adev = out->dev;
2366 int snd_scard_state = get_snd_card_state(adev);
2367
2368 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2369 status = compress_pause(out->compr);
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302373 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374 audio_extn_dts_notify_playback_state(out->usecase, 0,
2375 out->sample_rate, popcount(out->channel_mask),
2376 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 }
2378 pthread_mutex_unlock(&out->lock);
2379 }
2380 return status;
2381}
2382
2383static int out_resume(struct audio_stream_out* stream)
2384{
2385 struct stream_out *out = (struct stream_out *)stream;
2386 int status = -ENOSYS;
2387 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002388 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002389 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 status = 0;
2391 pthread_mutex_lock(&out->lock);
2392 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302393 struct audio_device *adev = out->dev;
2394 int snd_scard_state = get_snd_card_state(adev);
2395
2396 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2397 status = compress_resume(out->compr);
2398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002400
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302401 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2403 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 }
2405 pthread_mutex_unlock(&out->lock);
2406 }
2407 return status;
2408}
2409
2410static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2411{
2412 struct stream_out *out = (struct stream_out *)stream;
2413 int status = -ENOSYS;
2414 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002415 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 pthread_mutex_lock(&out->lock);
2417 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2418 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2419 else
2420 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2421 pthread_mutex_unlock(&out->lock);
2422 }
2423 return status;
2424}
2425
2426static int out_flush(struct audio_stream_out* stream)
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002431 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 pthread_mutex_lock(&out->lock);
2433 stop_compressed_output_l(out);
2434 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002435 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 return 0;
2437 }
2438 return -ENOSYS;
2439}
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441/** audio_stream_in implementation **/
2442static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->config.rate;
2447}
2448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002449static int in_set_sample_rate(struct audio_stream *stream __unused,
2450 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451{
2452 return -ENOSYS;
2453}
2454
2455static size_t in_get_buffer_size(const struct audio_stream *stream)
2456{
2457 struct stream_in *in = (struct stream_in *)stream;
2458
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2460 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002461 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2462 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002463
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002464 return in->config.period_size *
2465 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466}
2467
2468static uint32_t in_get_channels(const struct audio_stream *stream)
2469{
2470 struct stream_in *in = (struct stream_in *)stream;
2471
2472 return in->channel_mask;
2473}
2474
2475static audio_format_t in_get_format(const struct audio_stream *stream)
2476{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 struct stream_in *in = (struct stream_in *)stream;
2478
2479 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002482static int in_set_format(struct audio_stream *stream __unused,
2483 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return -ENOSYS;
2486}
2487
2488static int in_standby(struct audio_stream *stream)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491 struct audio_device *adev = in->dev;
2492 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302493 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2494 stream, in->usecase, use_case_table[in->usecase]);
2495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2497 /* Ignore standby in case of voip call because the voip input
2498 * stream is closed in adev_close_input_stream()
2499 */
2500 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2501 return status;
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002505 if (!in->standby && in->is_st_session) {
2506 ALOGD("%s: sound trigger pcm stop lab", __func__);
2507 audio_extn_sound_trigger_stop_lab(in);
2508 in->standby = 1;
2509 }
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002512 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002514 if (in->pcm) {
2515 pcm_close(in->pcm);
2516 in->pcm = NULL;
2517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
2521 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002522 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 return status;
2524}
2525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002526static int in_dump(const struct audio_stream *stream __unused,
2527 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528{
2529 return 0;
2530}
2531
2532static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535 struct audio_device *adev = in->dev;
2536 struct str_parms *parms;
2537 char *str;
2538 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002539 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302541 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 parms = str_parms_create_str(kvpairs);
2543
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302544 if (!parms)
2545 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002548
2549 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2550 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 val = atoi(value);
2552 /* no audio source uses val == 0 */
2553 if ((in->source != val) && (val != 0)) {
2554 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002555 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2556 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2557 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2558 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002559 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002560 err = voice_extn_compress_voip_open_input_stream(in);
2561 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002562 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002563 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002564 }
2565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
2567 }
2568
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002569 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2570 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002572 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 in->device = val;
2574 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002575 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002576 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578 }
2579
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002580done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002582 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
2584 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302585error:
Eric Laurent994a6932013-07-17 11:51:42 -07002586 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 return ret;
2588}
2589
2590static char* in_get_parameters(const struct audio_stream *stream,
2591 const char *keys)
2592{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 struct stream_in *in = (struct stream_in *)stream;
2594 struct str_parms *query = str_parms_create_str(keys);
2595 char *str;
2596 char value[256];
2597 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002598
2599 if (!query || !reply) {
2600 ALOGE("in_get_parameters: failed to create query or reply");
2601 return NULL;
2602 }
2603
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002604 ALOGV("%s: enter: keys - %s", __func__, keys);
2605
2606 voice_extn_in_get_parameters(in, query, reply);
2607
2608 str = str_parms_to_str(reply);
2609 str_parms_destroy(query);
2610 str_parms_destroy(reply);
2611
2612 ALOGV("%s: exit: returns - %s", __func__, str);
2613 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002616static int in_set_gain(struct audio_stream_in *stream __unused,
2617 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618{
2619 return 0;
2620}
2621
2622static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2623 size_t bytes)
2624{
2625 struct stream_in *in = (struct stream_in *)stream;
2626 struct audio_device *adev = in->dev;
2627 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302628 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302631
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002632 if (in->is_st_session) {
2633 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2634 /* Read from sound trigger HAL */
2635 audio_extn_sound_trigger_read(in, buffer, bytes);
2636 pthread_mutex_unlock(&in->lock);
2637 return bytes;
2638 }
2639
2640 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2641 ALOGD(" %s: sound card is not active/SSR state", __func__);
2642 ret= -EIO;;
2643 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302644 }
2645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002647 pthread_mutex_lock(&adev->lock);
2648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2649 ret = voice_extn_compress_voip_start_input_stream(in);
2650 else
2651 ret = start_input_stream(in);
2652 pthread_mutex_unlock(&adev->lock);
2653 if (ret != 0) {
2654 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
2656 in->standby = 0;
2657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
2659 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002660 if (audio_extn_ssr_get_enabled() &&
2661 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002662 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002663 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2664 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002665 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2666 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002667 else
2668 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302669 if (ret < 0)
2670 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672
2673 /*
2674 * Instead of writing zeroes here, we could trust the hardware
2675 * to always provide zeroes when muted.
2676 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302677 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2678 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 memset(buffer, 0, bytes);
2680
2681exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302682 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302683 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002684 if (-ENETRESET == ret)
2685 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 pthread_mutex_unlock(&in->lock);
2688
2689 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302690 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302691 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302692 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302693 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302694 in->standby = true;
2695 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302696 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002698 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002699 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302700 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 }
2702 return bytes;
2703}
2704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002705static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
2707 return 0;
2708}
2709
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710static int add_remove_audio_effect(const struct audio_stream *stream,
2711 effect_handle_t effect,
2712 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002714 struct stream_in *in = (struct stream_in *)stream;
2715 int status = 0;
2716 effect_descriptor_t desc;
2717
2718 status = (*effect)->get_descriptor(effect, &desc);
2719 if (status != 0)
2720 return status;
2721
2722 pthread_mutex_lock(&in->lock);
2723 pthread_mutex_lock(&in->dev->lock);
2724 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2725 in->enable_aec != enable &&
2726 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2727 in->enable_aec = enable;
2728 if (!in->standby)
2729 select_devices(in->dev, in->usecase);
2730 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002731 if (in->enable_ns != enable &&
2732 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2733 in->enable_ns = enable;
2734 if (!in->standby)
2735 select_devices(in->dev, in->usecase);
2736 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002737 pthread_mutex_unlock(&in->dev->lock);
2738 pthread_mutex_unlock(&in->lock);
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 return 0;
2741}
2742
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002743static int in_add_audio_effect(const struct audio_stream *stream,
2744 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
Eric Laurent994a6932013-07-17 11:51:42 -07002746 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002747 return add_remove_audio_effect(stream, effect, true);
2748}
2749
2750static int in_remove_audio_effect(const struct audio_stream *stream,
2751 effect_handle_t effect)
2752{
Eric Laurent994a6932013-07-17 11:51:42 -07002753 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002754 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755}
2756
2757static int adev_open_output_stream(struct audio_hw_device *dev,
2758 audio_io_handle_t handle,
2759 audio_devices_t devices,
2760 audio_output_flags_t flags,
2761 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002762 struct audio_stream_out **stream_out,
2763 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
2765 struct audio_device *adev = (struct audio_device *)dev;
2766 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002767 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002768 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302771
2772 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2773 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2774 ALOGE(" sound card is not active rejecting compress output open request");
2775 return -EINVAL;
2776 }
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2779
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302780 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2781 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2782 devices, flags, &out->stream);
2783
2784
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002785 if (!out) {
2786 return -ENOMEM;
2787 }
2788
Haynes Mathew George204045b2015-02-25 20:32:03 -08002789 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2790 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 if (devices == AUDIO_DEVICE_NONE)
2793 devices = AUDIO_DEVICE_OUT_SPEAKER;
2794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 out->flags = flags;
2796 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002797 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002798 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->sample_rate = config->sample_rate;
2800 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2801 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002802 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002803 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002804 out->non_blocking = 0;
2805 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302807 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2808 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002809 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2810 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2811
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002812 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002813 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2814 ret = read_hdmi_channel_masks(out);
2815
2816 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2817 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002818 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002819 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002820 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002821
2822 if (config->sample_rate == 0)
2823 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2824 if (config->channel_mask == 0)
2825 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2826
2827 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2830 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002832 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002834 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2835 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002836 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002837 ret = voice_extn_compress_voip_open_output_stream(out);
2838 if (ret != 0) {
2839 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2840 __func__, ret);
2841 goto error_open;
2842 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2844 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2845 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2846 ALOGE("%s: Unsupported Offload information", __func__);
2847 ret = -EINVAL;
2848 goto error_open;
2849 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002850
2851 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2852 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2853 ALOGV("read and update_pass through formats");
2854 ret = audio_extn_dolby_update_passt_formats(adev, out);
2855 if(ret != 0) {
2856 goto error_open;
2857 }
2858 if(config->offload_info.format == 0)
2859 config->offload_info.format = out->supported_formats[0];
2860 }
2861
Mingming Yin90310102013-11-13 16:57:00 -08002862 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002863 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 ALOGE("%s: Unsupported audio format", __func__);
2865 ret = -EINVAL;
2866 goto error_open;
2867 }
2868
2869 out->compr_config.codec = (struct snd_codec *)
2870 calloc(1, sizeof(struct snd_codec));
2871
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002872 if (!out->compr_config.codec) {
2873 ret = -ENOMEM;
2874 goto error_open;
2875 }
2876
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002877 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 if (config->offload_info.channel_mask)
2879 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002880 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002882 config->offload_info.channel_mask = config->channel_mask;
2883 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002884 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->sample_rate = config->offload_info.sample_rate;
2886
2887 out->stream.set_callback = out_set_callback;
2888 out->stream.pause = out_pause;
2889 out->stream.resume = out_resume;
2890 out->stream.drain = out_drain;
2891 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002892 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002894 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002895 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002896 audio_extn_dolby_get_snd_codec_id(adev, out,
2897 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002898 else
2899 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302901 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002902 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002903 platform_get_pcm_offload_buffer_size(&config->offload_info);
2904 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2905 out->compr_config.fragment_size =
2906 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 } else {
2908 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002909 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002910 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2912 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002913 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 out->compr_config.codec->bit_rate =
2915 config->offload_info.bit_rate;
2916 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002917 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302919 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002920 /*TODO: Do we need to change it for passthrough */
2921 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922
Manish Dewangan93672f12015-08-24 20:30:31 +05302923 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2924 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2925 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2926 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
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;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07002992 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2993 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2994 out->config = pcm_config_low_latency;
2995 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002996 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002997 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2999 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003001 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3002 format = AUDIO_FORMAT_PCM_16_BIT;
3003 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3004 out->config = pcm_config_deep_buffer;
3005 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003006 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003007 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003008 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003009 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003010 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003011 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 }
3013
Amit Shekhar1d896042014-10-03 13:16:09 -07003014 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3015 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003016 /* TODO remove this hardcoding and check why width is zero*/
3017 if (out->bit_width == 0)
3018 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003019 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3020 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003021 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303022 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003023 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3024 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3025 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003026 if(adev->primary_output == NULL)
3027 adev->primary_output = out;
3028 else {
3029 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003030 ret = -EEXIST;
3031 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003032 }
3033 }
3034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 /* Check if this usecase is already existing */
3036 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003037 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3038 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003041 ret = -EEXIST;
3042 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 }
3044 pthread_mutex_unlock(&adev->lock);
3045
3046 out->stream.common.get_sample_rate = out_get_sample_rate;
3047 out->stream.common.set_sample_rate = out_set_sample_rate;
3048 out->stream.common.get_buffer_size = out_get_buffer_size;
3049 out->stream.common.get_channels = out_get_channels;
3050 out->stream.common.get_format = out_get_format;
3051 out->stream.common.set_format = out_set_format;
3052 out->stream.common.standby = out_standby;
3053 out->stream.common.dump = out_dump;
3054 out->stream.common.set_parameters = out_set_parameters;
3055 out->stream.common.get_parameters = out_get_parameters;
3056 out->stream.common.add_audio_effect = out_add_audio_effect;
3057 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3058 out->stream.get_latency = out_get_latency;
3059 out->stream.set_volume = out_set_volume;
3060 out->stream.write = out_write;
3061 out->stream.get_render_position = out_get_render_position;
3062 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003066 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003067 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068
3069 config->format = out->stream.common.get_format(&out->stream.common);
3070 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3071 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3072
3073 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3075 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003076
3077 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3078 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3079 popcount(out->channel_mask), out->playback_started);
3080
Eric Laurent994a6932013-07-17 11:51:42 -07003081 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003083
3084error_open:
3085 free(out);
3086 *stream_out = NULL;
3087 ALOGD("%s: exit: ret %d", __func__, ret);
3088 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089}
3090
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003091static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 struct audio_stream_out *stream)
3093{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 struct stream_out *out = (struct stream_out *)stream;
3095 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003096 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303098 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3099
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003100 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303101 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003102 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303103 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003104 if(ret != 0)
3105 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3106 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003107 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003108 out_standby(&stream->common);
3109
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003110 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003111 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003113 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003114 if (out->compr_config.codec != NULL)
3115 free(out->compr_config.codec);
3116 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003117
3118 if (adev->voice_tx_output == out)
3119 adev->voice_tx_output = NULL;
3120
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 pthread_cond_destroy(&out->cond);
3122 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003124 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003127static void close_compress_sessions(struct audio_device *adev)
3128{
Mingming Yin7b762e72015-03-04 13:47:32 -08003129 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303130 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003131 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003132 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303133
3134 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003135 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303136 if (is_offload_usecase(usecase->id)) {
3137 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003138 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3139 out = usecase->stream.out;
3140 pthread_mutex_unlock(&adev->lock);
3141 out_standby(&out->stream.common);
3142 pthread_mutex_lock(&adev->lock);
3143 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303144 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003145 }
3146 pthread_mutex_unlock(&adev->lock);
3147}
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3150{
3151 struct audio_device *adev = (struct audio_device *)dev;
3152 struct str_parms *parms;
3153 char *str;
3154 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003155 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003156 int ret;
3157 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003159 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303162 if (!parms)
3163 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003164 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3165 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303166 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303167 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303168 struct listnode *node;
3169 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303171 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003172 //close compress sessions on OFFLINE status
3173 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303174 } else if (strstr(snd_card_status, "ONLINE")) {
3175 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303176 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303177 if (!platform_is_acdb_initialized(adev->platform)) {
3178 ret = platform_acdb_init(adev->platform);
3179 if(ret)
3180 ALOGE("acdb initialization is failed");
3181
3182 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303183 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303184 }
3185
3186 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003187 status = voice_set_parameters(adev, parms);
3188 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003189 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003191 status = platform_set_parameters(adev->platform, parms);
3192 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003193 goto done;
3194
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3196 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003197 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3199 adev->bluetooth_nrec = true;
3200 else
3201 adev->bluetooth_nrec = false;
3202 }
3203
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003204 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3205 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3207 adev->screen_off = false;
3208 else
3209 adev->screen_off = true;
3210 }
3211
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003212 ret = str_parms_get_int(parms, "rotation", &val);
3213 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003214 bool reverse_speakers = false;
3215 switch(val) {
3216 // FIXME: note that the code below assumes that the speakers are in the correct placement
3217 // relative to the user when the device is rotated 90deg from its default rotation. This
3218 // assumption is device-specific, not platform-specific like this code.
3219 case 270:
3220 reverse_speakers = true;
3221 break;
3222 case 0:
3223 case 90:
3224 case 180:
3225 break;
3226 default:
3227 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003228 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003230 if (status == 0) {
3231 if (adev->speaker_lr_swap != reverse_speakers) {
3232 adev->speaker_lr_swap = reverse_speakers;
3233 // only update the selected device if there is active pcm playback
3234 struct audio_usecase *usecase;
3235 struct listnode *node;
3236 list_for_each(node, &adev->usecase_list) {
3237 usecase = node_to_item(node, struct audio_usecase, list);
3238 if (usecase->type == PCM_PLAYBACK) {
3239 select_devices(adev, usecase->id);
3240 break;
3241 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003242 }
3243 }
3244 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003245 }
3246
Mingming Yin514a8bc2014-07-29 15:22:21 -07003247 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3248 if (ret >= 0) {
3249 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3250 adev->bt_wb_speech_enabled = true;
3251 else
3252 adev->bt_wb_speech_enabled = false;
3253 }
3254
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003255 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3256 if (ret >= 0) {
3257 val = atoi(value);
3258 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3259 ALOGV("cache new edid");
3260 platform_cache_edid(adev->platform);
3261 }
3262 }
3263
3264 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3265 if (ret >= 0) {
3266 val = atoi(value);
3267 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3268 ALOGV("invalidate cached edid");
3269 platform_invalidate_edid(adev->platform);
3270 }
3271 }
3272
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003273 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003274
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003275done:
3276 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003277 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303278error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003279 ALOGV("%s: exit with code(%d)", __func__, status);
3280 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281}
3282
3283static char* adev_get_parameters(const struct audio_hw_device *dev,
3284 const char *keys)
3285{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003286 struct audio_device *adev = (struct audio_device *)dev;
3287 struct str_parms *reply = str_parms_create();
3288 struct str_parms *query = str_parms_create_str(keys);
3289 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303290 char value[256] = {0};
3291 int ret = 0;
3292
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003293 if (!query || !reply) {
3294 ALOGE("adev_get_parameters: failed to create query or reply");
3295 return NULL;
3296 }
3297
Naresh Tannirud7205b62014-06-20 02:54:48 +05303298 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3299 sizeof(value));
3300 if (ret >=0) {
3301 int val = 1;
3302 pthread_mutex_lock(&adev->snd_card_status.lock);
3303 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3304 val = 0;
3305 pthread_mutex_unlock(&adev->snd_card_status.lock);
3306 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3307 goto exit;
3308 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003309
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003310 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003311 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003312 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003313 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303314 pthread_mutex_unlock(&adev->lock);
3315
Naresh Tannirud7205b62014-06-20 02:54:48 +05303316exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003317 str = str_parms_to_str(reply);
3318 str_parms_destroy(query);
3319 str_parms_destroy(reply);
3320
3321 ALOGV("%s: exit: returns - %s", __func__, str);
3322 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323}
3324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003325static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326{
3327 return 0;
3328}
3329
3330static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3331{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003332 int ret;
3333 struct audio_device *adev = (struct audio_device *)dev;
3334 pthread_mutex_lock(&adev->lock);
3335 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003336 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003337 pthread_mutex_unlock(&adev->lock);
3338 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339}
3340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003341static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3342 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return -ENOSYS;
3345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3348 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return -ENOSYS;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3354 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355{
3356 return -ENOSYS;
3357}
3358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003359static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3360 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361{
3362 return -ENOSYS;
3363}
3364
3365static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3366{
3367 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 pthread_mutex_lock(&adev->lock);
3370 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003371 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003373 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3374 voice_is_in_call(adev)) {
3375 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303376 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003377 adev->current_call_output = NULL;
3378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 }
3380 pthread_mutex_unlock(&adev->lock);
3381 return 0;
3382}
3383
3384static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3385{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003386 int ret;
3387
3388 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003389 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003390 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3391 pthread_mutex_unlock(&adev->lock);
3392
3393 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394}
3395
3396static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3397{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003398 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 return 0;
3400}
3401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003402static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 const struct audio_config *config)
3404{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003405 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003407 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3408 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409}
3410
3411static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003412 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 audio_devices_t devices,
3414 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003415 struct audio_stream_in **stream_in,
3416 audio_input_flags_t flags __unused,
3417 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003418 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419{
3420 struct audio_device *adev = (struct audio_device *)dev;
3421 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003422 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003423 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003424 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 *stream_in = NULL;
3427 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3428 return -EINVAL;
3429
3430 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003431
3432 if (!in) {
3433 ALOGE("failed to allocate input stream");
3434 return -ENOMEM;
3435 }
3436
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303437 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003438 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3439 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003441 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 in->stream.common.get_sample_rate = in_get_sample_rate;
3444 in->stream.common.set_sample_rate = in_set_sample_rate;
3445 in->stream.common.get_buffer_size = in_get_buffer_size;
3446 in->stream.common.get_channels = in_get_channels;
3447 in->stream.common.get_format = in_get_format;
3448 in->stream.common.set_format = in_set_format;
3449 in->stream.common.standby = in_standby;
3450 in->stream.common.dump = in_dump;
3451 in->stream.common.set_parameters = in_set_parameters;
3452 in->stream.common.get_parameters = in_get_parameters;
3453 in->stream.common.add_audio_effect = in_add_audio_effect;
3454 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3455 in->stream.set_gain = in_set_gain;
3456 in->stream.read = in_read;
3457 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3458
3459 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003460 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->standby = 1;
3463 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003464 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465
3466 /* Update config params with the requested sample rate and channels */
3467 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003468 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3469 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3470 is_low_latency = true;
3471#if LOW_LATENCY_CAPTURE_USE_CASE
3472 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3473#endif
3474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003477 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003479 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303480 if (adev->mode != AUDIO_MODE_IN_CALL) {
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003484 if (config->sample_rate == 0)
3485 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3486 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3487 config->sample_rate != 8000) {
3488 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3489 ret = -EINVAL;
3490 goto err_open;
3491 }
3492 if (config->format == AUDIO_FORMAT_DEFAULT)
3493 config->format = AUDIO_FORMAT_PCM_16_BIT;
3494 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3495 config->format = AUDIO_FORMAT_PCM_16_BIT;
3496 ret = -EINVAL;
3497 goto err_open;
3498 }
3499
3500 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3501 in->config = pcm_config_afe_proxy_record;
3502 in->config.channels = channel_count;
3503 in->config.rate = config->sample_rate;
3504 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003505 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003506 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003507 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3508 ret = -EINVAL;
3509 goto err_open;
3510 }
3511 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003512 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003513 }
Mingming Yine62d7842013-10-25 16:26:03 -07003514 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003515 audio_extn_compr_cap_format_supported(config->format) &&
3516 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003517 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 } else {
3519 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003520 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003521 buffer_size = get_input_buffer_size(config->sample_rate,
3522 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003523 channel_count,
3524 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003525 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003526 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3527 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3528 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3529 (in->config.rate == 8000 || in->config.rate == 16000) &&
3530 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3531 voice_extn_compress_voip_open_input_stream(in);
3532 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003535 /* This stream could be for sound trigger lab,
3536 get sound trigger pcm if present */
3537 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303538 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003541 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003542 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
3544err_open:
3545 free(in);
3546 *stream_in = NULL;
3547 return ret;
3548}
3549
3550static void adev_close_input_stream(struct audio_hw_device *dev,
3551 struct audio_stream_in *stream)
3552{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003553 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003554 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003555 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303556
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303557 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003558
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303559 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003560 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303561
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003562 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303563 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003564 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303565 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003566 if (ret != 0)
3567 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3568 __func__, ret);
3569 } else
3570 in_standby(&stream->common);
3571
Mingming Yin7b762e72015-03-04 13:47:32 -08003572 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003574 audio_extn_ssr_deinit();
3575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
Mingming Yine62d7842013-10-25 16:26:03 -07003577 if(audio_extn_compr_cap_enabled() &&
3578 audio_extn_compr_cap_format_supported(in->config.format))
3579 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003580
3581 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 return;
3583}
3584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003585static int adev_dump(const audio_hw_device_t *device __unused,
3586 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 return 0;
3589}
3590
3591static int adev_close(hw_device_t *device)
3592{
3593 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003594
3595 if (!adev)
3596 return 0;
3597
3598 pthread_mutex_lock(&adev_init_lock);
3599
3600 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003601 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003602 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003603 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003604 audio_route_free(adev->audio_route);
3605 free(adev->snd_dev_ref_cnt);
3606 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003607 free(device);
3608 adev = NULL;
3609 }
3610 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 return 0;
3612}
3613
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003614/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3615 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3616 * just that it _might_ work.
3617 */
3618static int period_size_is_plausible_for_low_latency(int period_size)
3619{
3620 switch (period_size) {
3621 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003622 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003623 case 240:
3624 case 320:
3625 case 480:
3626 return 1;
3627 default:
3628 return 0;
3629 }
3630}
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632static int adev_open(const hw_module_t *module, const char *name,
3633 hw_device_t **device)
3634{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003635 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003637 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3639
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003640 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003641 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003642 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003643 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003644 ALOGD("%s: returning existing instance of adev", __func__);
3645 ALOGD("%s: exit", __func__);
3646 pthread_mutex_unlock(&adev_init_lock);
3647 return 0;
3648 }
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 adev = calloc(1, sizeof(struct audio_device));
3651
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003652 if (!adev) {
3653 pthread_mutex_unlock(&adev_init_lock);
3654 return -ENOMEM;
3655 }
3656
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003657 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3660 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3661 adev->device.common.module = (struct hw_module_t *)module;
3662 adev->device.common.close = adev_close;
3663
3664 adev->device.init_check = adev_init_check;
3665 adev->device.set_voice_volume = adev_set_voice_volume;
3666 adev->device.set_master_volume = adev_set_master_volume;
3667 adev->device.get_master_volume = adev_get_master_volume;
3668 adev->device.set_master_mute = adev_set_master_mute;
3669 adev->device.get_master_mute = adev_get_master_mute;
3670 adev->device.set_mode = adev_set_mode;
3671 adev->device.set_mic_mute = adev_set_mic_mute;
3672 adev->device.get_mic_mute = adev_get_mic_mute;
3673 adev->device.set_parameters = adev_set_parameters;
3674 adev->device.get_parameters = adev_get_parameters;
3675 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3676 adev->device.open_output_stream = adev_open_output_stream;
3677 adev->device.close_output_stream = adev_close_output_stream;
3678 adev->device.open_input_stream = adev_open_input_stream;
3679 adev->device.close_input_stream = adev_close_input_stream;
3680 adev->device.dump = adev_dump;
3681
3682 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003684 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003685 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003688 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003689 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003690 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003691 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003692 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003693 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003694 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303695 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303696
3697 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3698 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003700 adev->platform = platform_init(adev);
3701 if (!adev->platform) {
3702 free(adev->snd_dev_ref_cnt);
3703 free(adev);
3704 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3705 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003706 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003707 return -EINVAL;
3708 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003709
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3711
Eric Laurentc4aef752013-09-12 17:45:53 -07003712 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3713 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3714 if (adev->visualizer_lib == NULL) {
3715 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3716 } else {
3717 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3718 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003719 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003720 "visualizer_hal_start_output");
3721 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003722 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003723 "visualizer_hal_stop_output");
3724 }
3725 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003726 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003727 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003728
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3730 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3731 if (adev->offload_effects_lib == NULL) {
3732 ALOGE("%s: DLOPEN failed for %s", __func__,
3733 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3734 } else {
3735 ALOGV("%s: DLOPEN successful for %s", __func__,
3736 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3737 adev->offload_effects_start_output =
3738 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3739 "offload_effects_bundle_hal_start_output");
3740 adev->offload_effects_stop_output =
3741 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3742 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003743 adev->offload_effects_set_hpx_state =
3744 (int (*)(bool))dlsym(adev->offload_effects_lib,
3745 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303746 adev->offload_effects_get_parameters =
3747 (void (*)(struct str_parms *, struct str_parms *))
3748 dlsym(adev->offload_effects_lib,
3749 "offload_effects_bundle_get_parameters");
3750 adev->offload_effects_set_parameters =
3751 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3752 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003753 }
3754 }
3755
Mingming Yin514a8bc2014-07-29 15:22:21 -07003756 adev->bt_wb_speech_enabled = false;
3757
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003758 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 *device = &adev->device.common;
3760
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003761 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3762 &adev->streams_output_cfg_list);
3763
Kiran Kandi910e1862013-10-29 13:29:42 -07003764 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003765
3766 char value[PROPERTY_VALUE_MAX];
3767 int trial;
3768 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3769 trial = atoi(value);
3770 if (period_size_is_plausible_for_low_latency(trial)) {
3771 pcm_config_low_latency.period_size = trial;
3772 pcm_config_low_latency.start_threshold = trial / 4;
3773 pcm_config_low_latency.avail_min = trial / 4;
3774 configured_low_latency_capture_period_size = trial;
3775 }
3776 }
3777 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3778 trial = atoi(value);
3779 if (period_size_is_plausible_for_low_latency(trial)) {
3780 configured_low_latency_capture_period_size = trial;
3781 }
3782 }
3783
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003784 pthread_mutex_unlock(&adev_init_lock);
3785
Eric Laurent994a6932013-07-17 11:51:42 -07003786 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 return 0;
3788}
3789
3790static struct hw_module_methods_t hal_module_methods = {
3791 .open = adev_open,
3792};
3793
3794struct audio_module HAL_MODULE_INFO_SYM = {
3795 .common = {
3796 .tag = HARDWARE_MODULE_TAG,
3797 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3798 .hal_api_version = HARDWARE_HAL_API_VERSION,
3799 .id = AUDIO_HARDWARE_MODULE_ID,
3800 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003801 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 .methods = &hal_module_methods,
3803 },
3804};