blob: 7d9836fdd181cd8f2686ecd1ea5c3117e2deea34 [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
Naresh Tanniru4a080142015-06-15 10:35:19 -07001143 ALOGV("%s: pcm_prepare start", __func__);
1144 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001145 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001146
Eric Laurentc8400632013-02-14 19:04:54 -08001147 return ret;
1148
1149error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301151 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001152
1153error_config:
1154 adev->active_input = NULL;
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301155 /*
1156 * sleep 50ms to allow sufficient time for kernel
1157 * drivers to recover incases like SSR.
1158 */
1159 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001161
1162 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163}
1164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001165/* must be called with out->lock locked */
1166static int send_offload_cmd_l(struct stream_out* out, int command)
1167{
1168 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1169
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001170 if (!cmd) {
1171 ALOGE("failed to allocate mem for command 0x%x", command);
1172 return -ENOMEM;
1173 }
1174
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001175 ALOGVV("%s %d", __func__, command);
1176
1177 cmd->cmd = command;
1178 list_add_tail(&out->offload_cmd_list, &cmd->node);
1179 pthread_cond_signal(&out->offload_cond);
1180 return 0;
1181}
1182
1183/* must be called iwth out->lock locked */
1184static void stop_compressed_output_l(struct stream_out *out)
1185{
1186 out->offload_state = OFFLOAD_STATE_IDLE;
1187 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001188 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001189 if (out->compr != NULL) {
1190 compress_stop(out->compr);
1191 while (out->offload_thread_blocked) {
1192 pthread_cond_wait(&out->cond, &out->lock);
1193 }
1194 }
1195}
1196
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001197bool is_offload_usecase(audio_usecase_t uc_id)
1198{
1199 unsigned int i;
1200 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1201 if (uc_id == offload_usecases[i])
1202 return true;
1203 }
1204 return false;
1205}
1206
1207static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1208{
1209 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1210 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1211 char value[PROPERTY_VALUE_MAX] = {0};
1212
1213 property_get("audio.offload.multiple.enabled", value, NULL);
1214 if (!(atoi(value) || !strncmp("true", value, 4)))
1215 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1216
1217 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1218 for (i = 0; i < num_usecase; i++) {
1219 if (!(adev->offload_usecases_state & (0x1<<i))) {
1220 adev->offload_usecases_state |= 0x1 << i;
1221 ret = offload_usecases[i];
1222 break;
1223 }
1224 }
1225 ALOGV("%s: offload usecase is %d", __func__, ret);
1226 return ret;
1227}
1228
1229static void free_offload_usecase(struct audio_device *adev,
1230 audio_usecase_t uc_id)
1231{
1232 unsigned int i;
1233 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1234 if (offload_usecases[i] == uc_id) {
1235 adev->offload_usecases_state &= ~(0x1<<i);
1236 break;
1237 }
1238 }
1239 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1240}
1241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001242static void *offload_thread_loop(void *context)
1243{
1244 struct stream_out *out = (struct stream_out *) context;
1245 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001246 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001247
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001248 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1249 set_sched_policy(0, SP_FOREGROUND);
1250 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1251
1252 ALOGV("%s", __func__);
1253 pthread_mutex_lock(&out->lock);
1254 for (;;) {
1255 struct offload_cmd *cmd = NULL;
1256 stream_callback_event_t event;
1257 bool send_callback = false;
1258
1259 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1260 __func__, list_empty(&out->offload_cmd_list),
1261 out->offload_state);
1262 if (list_empty(&out->offload_cmd_list)) {
1263 ALOGV("%s SLEEPING", __func__);
1264 pthread_cond_wait(&out->offload_cond, &out->lock);
1265 ALOGV("%s RUNNING", __func__);
1266 continue;
1267 }
1268
1269 item = list_head(&out->offload_cmd_list);
1270 cmd = node_to_item(item, struct offload_cmd, node);
1271 list_remove(item);
1272
1273 ALOGVV("%s STATE %d CMD %d out->compr %p",
1274 __func__, out->offload_state, cmd->cmd, out->compr);
1275
1276 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1277 free(cmd);
1278 break;
1279 }
1280
1281 if (out->compr == NULL) {
1282 ALOGE("%s: Compress handle is NULL", __func__);
1283 pthread_cond_signal(&out->cond);
1284 continue;
1285 }
1286 out->offload_thread_blocked = true;
1287 pthread_mutex_unlock(&out->lock);
1288 send_callback = false;
1289 switch(cmd->cmd) {
1290 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001293 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001294 send_callback = true;
1295 event = STREAM_CBK_EVENT_WRITE_READY;
1296 break;
1297 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001298 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301299 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001300 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301301 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001302 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301303 if (ret < 0)
1304 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301305 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301306 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001307 compress_drain(out->compr);
1308 else
1309 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301310 if (ret != -ENETRESET) {
1311 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301312 pthread_mutex_lock(&out->lock);
1313 out->send_new_metadata = 1;
1314 out->send_next_track_params = true;
1315 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301316 event = STREAM_CBK_EVENT_DRAIN_READY;
1317 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1318 } else
1319 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 break;
1321 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001322 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001323 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001324 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001325 send_callback = true;
1326 event = STREAM_CBK_EVENT_DRAIN_READY;
1327 break;
1328 default:
1329 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1330 break;
1331 }
1332 pthread_mutex_lock(&out->lock);
1333 out->offload_thread_blocked = false;
1334 pthread_cond_signal(&out->cond);
vivek mehtacc70d4b2015-09-25 14:07:43 -07001335 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001336 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001337 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001338 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001339 free(cmd);
1340 }
1341
1342 pthread_cond_signal(&out->cond);
1343 while (!list_empty(&out->offload_cmd_list)) {
1344 item = list_head(&out->offload_cmd_list);
1345 list_remove(item);
1346 free(node_to_item(item, struct offload_cmd, node));
1347 }
1348 pthread_mutex_unlock(&out->lock);
1349
1350 return NULL;
1351}
1352
1353static int create_offload_callback_thread(struct stream_out *out)
1354{
1355 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1356 list_init(&out->offload_cmd_list);
1357 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1358 offload_thread_loop, out);
1359 return 0;
1360}
1361
1362static int destroy_offload_callback_thread(struct stream_out *out)
1363{
1364 pthread_mutex_lock(&out->lock);
1365 stop_compressed_output_l(out);
1366 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1367
1368 pthread_mutex_unlock(&out->lock);
1369 pthread_join(out->offload_thread, (void **) NULL);
1370 pthread_cond_destroy(&out->offload_cond);
1371
1372 return 0;
1373}
1374
Eric Laurent07eeafd2013-10-06 12:52:49 -07001375static bool allow_hdmi_channel_config(struct audio_device *adev)
1376{
1377 struct listnode *node;
1378 struct audio_usecase *usecase;
1379 bool ret = true;
1380
1381 list_for_each(node, &adev->usecase_list) {
1382 usecase = node_to_item(node, struct audio_usecase, list);
1383 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1384 /*
1385 * If voice call is already existing, do not proceed further to avoid
1386 * disabling/enabling both RX and TX devices, CSD calls, etc.
1387 * Once the voice call done, the HDMI channels can be configured to
1388 * max channels of remaining use cases.
1389 */
1390 if (usecase->id == USECASE_VOICE_CALL) {
1391 ALOGD("%s: voice call is active, no change in HDMI channels",
1392 __func__);
1393 ret = false;
1394 break;
1395 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1396 ALOGD("%s: multi channel playback is active, "
1397 "no change in HDMI channels", __func__);
1398 ret = false;
1399 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001400 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001401 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001402 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1403 ", no change in HDMI channels", __func__,
1404 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001405 ret = false;
1406 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001407 }
1408 }
1409 }
1410 return ret;
1411}
1412
1413static int check_and_set_hdmi_channels(struct audio_device *adev,
1414 unsigned int channels)
1415{
1416 struct listnode *node;
1417 struct audio_usecase *usecase;
1418
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001419 unsigned int supported_channels = platform_edid_get_max_channels(
1420 adev->platform);
1421 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001422 /* Check if change in HDMI channel config is allowed */
1423 if (!allow_hdmi_channel_config(adev))
1424 return 0;
1425
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001426 if (channels > supported_channels)
1427 channels = supported_channels;
1428
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001430 ALOGD("%s: Requested channels are same as current channels(%d)",
1431 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432 return 0;
1433 }
1434
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001435 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001436 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001437 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001438 adev->cur_hdmi_channels = channels;
1439
1440 /*
1441 * Deroute all the playback streams routed to HDMI so that
1442 * the back end is deactivated. Note that backend will not
1443 * be deactivated if any one stream is connected to it.
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 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001450 }
1451 }
1452
1453 /*
1454 * Enable all the streams disabled above. Now the HDMI backend
1455 * will be activated with new channel configuration
1456 */
1457 list_for_each(node, &adev->usecase_list) {
1458 usecase = node_to_item(node, struct audio_usecase, list);
1459 if (usecase->type == PCM_PLAYBACK &&
1460 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001461 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001462 }
1463 }
1464
1465 return 0;
1466}
1467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468static int stop_output_stream(struct stream_out *out)
1469{
1470 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471 struct audio_usecase *uc_info;
1472 struct audio_device *adev = out->dev;
1473
Eric Laurent994a6932013-07-17 11:51:42 -07001474 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476 uc_info = get_usecase_from_list(adev, out->usecase);
1477 if (uc_info == NULL) {
1478 ALOGE("%s: Could not find the usecase (%d) in the list",
1479 __func__, out->usecase);
1480 return -EINVAL;
1481 }
1482
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001483 if (is_offload_usecase(out->usecase) &&
1484 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001485 if (adev->visualizer_stop_output != NULL)
1486 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001487
1488 audio_extn_dts_remove_state_notifier_node(out->usecase);
1489
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001490 if (adev->offload_effects_stop_output != NULL)
1491 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1492 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001493
Eric Laurent150dbfe2013-02-27 14:31:02 -08001494 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001495 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001496
1497 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001498 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001500 list_remove(&uc_info->list);
1501 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001503 if (is_offload_usecase(out->usecase) &&
1504 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1505 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1506 ALOGV("Disable passthrough , reset mixer to pcm");
1507 /* NO_PASSTHROUGH */
1508 out->compr_config.codec->compr_passthr = 0;
1509 audio_extn_dolby_set_hdmi_config(adev, out);
1510 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1511 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001512 /* Must be called after removing the usecase from list */
1513 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1514 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1515
Eric Laurent994a6932013-07-17 11:51:42 -07001516 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 return ret;
1518}
1519
1520int start_output_stream(struct stream_out *out)
1521{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001523 int sink_channels = 0;
1524 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 struct audio_usecase *uc_info;
1526 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301527 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001529 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1530 ret = -EINVAL;
1531 goto error_config;
1532 }
1533
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301534 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1535 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1536 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301537
Naresh Tanniru80659832014-06-04 18:17:56 +05301538 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301539 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301540 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301541 goto error_config;
1542 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301543
Eric Laurentb23d5282013-05-14 15:27:20 -07001544 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 if (out->pcm_device_id < 0) {
1546 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1547 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001548 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001549 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 }
1551
1552 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001553
1554 if (!uc_info) {
1555 ret = -ENOMEM;
1556 goto error_config;
1557 }
1558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 uc_info->id = out->usecase;
1560 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001561 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562 uc_info->devices = out->devices;
1563 uc_info->in_snd_device = SND_DEVICE_NONE;
1564 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001566 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001567 if (is_offload_usecase(out->usecase)) {
1568 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001569 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1570 }
1571 }
Mingming Yin9c041392014-05-01 15:37:31 -07001572 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1573 if (!strncmp("true", prop_value, 4)) {
1574 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001575 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1576 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001577 check_and_set_hdmi_channels(adev, sink_channels);
1578 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001579 if (is_offload_usecase(out->usecase)) {
1580 unsigned int ch_count = out->compr_config.codec->ch_in;
1581 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1582 /* backend channel config for passthrough stream is stereo */
1583 ch_count = 2;
1584 check_and_set_hdmi_channels(adev, ch_count);
1585 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001586 check_and_set_hdmi_channels(adev, out->config.channels);
1587 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001588 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001589 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001590 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 select_devices(adev, out->usecase);
1593
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001594 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1595 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001596 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001597 unsigned int flags = PCM_OUT;
1598 unsigned int pcm_open_retry_count = 0;
1599 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1600 flags |= PCM_MMAP | PCM_NOIRQ;
1601 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1602 } else
1603 flags |= PCM_MONOTONIC;
1604
1605 while (1) {
1606 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1607 flags, &out->config);
1608 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1609 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1610 if (out->pcm != NULL) {
1611 pcm_close(out->pcm);
1612 out->pcm = NULL;
1613 }
1614 if (pcm_open_retry_count-- == 0) {
1615 ret = -EIO;
1616 goto error_open;
1617 }
1618 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1619 continue;
1620 }
1621 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001623
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001624 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1625 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001626
1627 ALOGV("%s: pcm_prepare start", __func__);
1628 if (pcm_is_ready(out->pcm))
1629 pcm_prepare(out->pcm);
1630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001631 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001632 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1633 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001635 out->compr = compress_open(adev->snd_card,
1636 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001637 COMPRESS_IN, &out->compr_config);
1638 if (out->compr && !is_compress_ready(out->compr)) {
1639 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1640 compress_close(out->compr);
1641 out->compr = NULL;
1642 ret = -EIO;
1643 goto error_open;
1644 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301645 /* compress_open sends params of the track, so reset the flag here */
1646 out->is_compr_metadata_avail = false;
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648 if (out->offload_callback)
1649 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001650
Fred Oh3f43e742015-03-04 18:42:34 -08001651 /* Since small bufs uses blocking writes, a write will be blocked
1652 for the default max poll time (20s) in the event of an SSR.
1653 Reduce the poll time to observe and deal with SSR faster.
1654 */
1655 if (out->use_small_bufs) {
1656 compress_set_max_poll_wait(out->compr, 1000);
1657 }
1658
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001659 audio_extn_dts_create_state_notifier_node(out->usecase);
1660 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1661 popcount(out->channel_mask),
1662 out->playback_started);
1663
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001664#ifdef DS1_DOLBY_DDP_ENABLED
1665 if (audio_extn_is_dolby_format(out->format))
1666 audio_extn_dolby_send_ddp_endp_params(adev);
1667#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001668 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1669 if (adev->visualizer_start_output != NULL)
1670 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1671 if (adev->offload_effects_start_output != NULL)
1672 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001673 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001676
Eric Laurent994a6932013-07-17 11:51:42 -07001677 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001682error_config:
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301683 /*
1684 * sleep 50ms to allow sufficient time for kernel
1685 * drivers to recover incases like SSR.
1686 */
1687 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001688 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689}
1690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691static int check_input_parameters(uint32_t sample_rate,
1692 audio_format_t format,
1693 int channel_count)
1694{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001695 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001697 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001698 !voice_extn_compress_voip_is_format_supported(format) &&
1699 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001700
1701 switch (channel_count) {
1702 case 1:
1703 case 2:
1704 case 6:
1705 break;
1706 default:
1707 ret = -EINVAL;
1708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
1710 switch (sample_rate) {
1711 case 8000:
1712 case 11025:
1713 case 12000:
1714 case 16000:
1715 case 22050:
1716 case 24000:
1717 case 32000:
1718 case 44100:
1719 case 48000:
1720 break;
1721 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001722 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 }
1724
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001725 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
1728static size_t get_input_buffer_size(uint32_t sample_rate,
1729 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001730 int channel_count,
1731 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732{
1733 size_t size = 0;
1734
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001735 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1736 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001738 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001739 if (is_low_latency)
1740 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001741 /* ToDo: should use frame_size computed based on the format and
1742 channel_count here. */
1743 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001745 /* make sure the size is multiple of 32 bytes
1746 * At 48 kHz mono 16-bit PCM:
1747 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1748 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1749 */
1750 size += 0x1f;
1751 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001752
1753 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
1756static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1757{
1758 struct stream_out *out = (struct stream_out *)stream;
1759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761}
1762
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001763static int out_set_sample_rate(struct audio_stream *stream __unused,
1764 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765{
1766 return -ENOSYS;
1767}
1768
1769static size_t out_get_buffer_size(const struct audio_stream *stream)
1770{
1771 struct stream_out *out = (struct stream_out *)stream;
1772
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001773 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001775 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1776 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001778 return out->config.period_size *
1779 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780}
1781
1782static uint32_t out_get_channels(const struct audio_stream *stream)
1783{
1784 struct stream_out *out = (struct stream_out *)stream;
1785
1786 return out->channel_mask;
1787}
1788
1789static audio_format_t out_get_format(const struct audio_stream *stream)
1790{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 struct stream_out *out = (struct stream_out *)stream;
1792
1793 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794}
1795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001796static int out_set_format(struct audio_stream *stream __unused,
1797 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798{
1799 return -ENOSYS;
1800}
1801
1802static int out_standby(struct audio_stream *stream)
1803{
1804 struct stream_out *out = (struct stream_out *)stream;
1805 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301807 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1808 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001809 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1810 /* Ignore standby in case of voip call because the voip output
1811 * stream is closed in adev_close_output_stream()
1812 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301813 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001814 return 0;
1815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001819 if (adev->adm_deregister_stream)
1820 adev->adm_deregister_stream(adev->adm_data, out->handle);
1821
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001822 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001824 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 if (out->pcm) {
1826 pcm_close(out->pcm);
1827 out->pcm = NULL;
1828 }
1829 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001830 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301832 out->send_next_track_params = false;
1833 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 out->gapless_mdata.encoder_delay = 0;
1835 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 if (out->compr != NULL) {
1837 compress_close(out->compr);
1838 out->compr = NULL;
1839 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001842 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 }
1844 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001845 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 return 0;
1847}
1848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001849static int out_dump(const struct audio_stream *stream __unused,
1850 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851{
1852 return 0;
1853}
1854
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1856{
1857 int ret = 0;
1858 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001859
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001861 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 return -EINVAL;
1863 }
1864
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301865 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001866
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1868 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301869 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1872 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301873 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 }
1875
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001876 ALOGV("%s new encoder delay %u and padding %u", __func__,
1877 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1878
1879 return 0;
1880}
1881
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001882static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1883{
1884 return out == adev->primary_output || out == adev->voice_tx_output;
1885}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1888{
1889 struct stream_out *out = (struct stream_out *)stream;
1890 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001891 struct audio_usecase *usecase;
1892 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 struct str_parms *parms;
1894 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001895 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001896 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897
sangwoobc677242013-08-08 16:53:43 +09001898 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301901 if (!parms)
1902 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001903 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1904 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001907 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301910 * When HDMI cable is unplugged/usb hs is disconnected the
1911 * music playback is paused and the policy manager sends routing=0
1912 * But the audioflingercontinues to write data until standby time
1913 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001914 * Avoid this by routing audio to speaker until standby.
1915 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301916 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1917 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001919 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1920 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921 }
1922
1923 /*
1924 * select_devices() call below switches all the usecases on the same
1925 * backend to the new device. Refer to check_usecases_codec_backend() in
1926 * the select_devices(). But how do we undo this?
1927 *
1928 * For example, music playback is active on headset (deep-buffer usecase)
1929 * and if we go to ringtones and select a ringtone, low-latency usecase
1930 * will be started on headset+speaker. As we can't enable headset+speaker
1931 * and headset devices at the same time, select_devices() switches the music
1932 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1933 * So when the ringtone playback is completed, how do we undo the same?
1934 *
1935 * We are relying on the out_set_parameters() call on deep-buffer output,
1936 * once the ringtone playback is ended.
1937 * NOTE: We should not check if the current devices are same as new devices.
1938 * Because select_devices() must be called to switch back the music
1939 * playback to headset.
1940 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001941 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001942 out->devices = val;
1943
1944 if (!out->standby)
1945 select_devices(adev, out->usecase);
1946
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001947 if (output_drives_call(adev, out)) {
1948 if(!voice_is_in_call(adev)) {
1949 if (adev->mode == AUDIO_MODE_IN_CALL) {
1950 adev->current_call_output = out;
1951 ret = voice_start_call(adev);
1952 }
1953 } else {
1954 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001955 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001956 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001957 }
1958 }
1959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001961 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001963
1964 if (out == adev->primary_output) {
1965 pthread_mutex_lock(&adev->lock);
1966 audio_extn_set_parameters(adev, parms);
1967 pthread_mutex_unlock(&adev->lock);
1968 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001969 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001970 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001971 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001972
1973 audio_extn_dts_create_state_notifier_node(out->usecase);
1974 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1975 popcount(out->channel_mask),
1976 out->playback_started);
1977
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001978 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001979 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301982error:
Eric Laurent994a6932013-07-17 11:51:42 -07001983 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 return ret;
1985}
1986
1987static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1988{
1989 struct stream_out *out = (struct stream_out *)stream;
1990 struct str_parms *query = str_parms_create_str(keys);
1991 char *str;
1992 char value[256];
1993 struct str_parms *reply = str_parms_create();
1994 size_t i, j;
1995 int ret;
1996 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001997
1998 if (!query || !reply) {
1999 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2000 return NULL;
2001 }
2002
Eric Laurent994a6932013-07-17 11:51:42 -07002003 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2005 if (ret >= 0) {
2006 value[0] = '\0';
2007 i = 0;
2008 while (out->supported_channel_masks[i] != 0) {
2009 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2010 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2011 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002012 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002014 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 first = false;
2016 break;
2017 }
2018 }
2019 i++;
2020 }
2021 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2022 str = str_parms_to_str(reply);
2023 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002024 voice_extn_out_get_parameters(out, query, reply);
2025 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002026 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002027 free(str);
2028 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002031
2032 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2033 if (ret >= 0) {
2034 value[0] = '\0';
2035 i = 0;
2036 first = true;
2037 while (out->supported_formats[i] != 0) {
2038 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2039 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2040 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002041 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002042 }
2043 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2044 first = false;
2045 break;
2046 }
2047 }
2048 i++;
2049 }
2050 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2051 str = str_parms_to_str(reply);
2052 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 str_parms_destroy(query);
2054 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002055 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 return str;
2057}
2058
2059static uint32_t out_get_latency(const struct audio_stream_out *stream)
2060{
2061 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002062 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063
Alexy Josephaa54c872014-12-03 02:46:47 -08002064 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002065 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002066 } else {
2067 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002069 }
2070
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302071 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002072 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073}
2074
2075static int out_set_volume(struct audio_stream_out *stream, float left,
2076 float right)
2077{
Eric Laurenta9024de2013-04-04 09:19:12 -07002078 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 int volume[2];
2080
Eric Laurenta9024de2013-04-04 09:19:12 -07002081 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2082 /* only take left channel into account: the API is for stereo anyway */
2083 out->muted = (left == 0.0f);
2084 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002085 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002086 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2087 /*
2088 * Set mute or umute on HDMI passthrough stream.
2089 * Only take left channel into account.
2090 * Mute is 0 and unmute 1
2091 */
2092 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2093 } else {
2094 char mixer_ctl_name[128];
2095 struct audio_device *adev = out->dev;
2096 struct mixer_ctl *ctl;
2097 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002098 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002100 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2101 "Compress Playback %d Volume", pcm_device_id);
2102 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2103 if (!ctl) {
2104 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2105 __func__, mixer_ctl_name);
2106 return -EINVAL;
2107 }
2108 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2109 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2110 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2111 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002113 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 return -ENOSYS;
2116}
2117
2118static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2119 size_t bytes)
2120{
2121 struct stream_out *out = (struct stream_out *)stream;
2122 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302123 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002124 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002129 // increase written size during SSR to avoid mismatch
2130 // with the written frames count in AF
2131 if (!is_offload_usecase(out->usecase))
2132 out->written += bytes / (out->config.channels * sizeof(short));
2133
Naresh Tanniru80659832014-06-04 18:17:56 +05302134 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302135 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302136 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302137 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002138 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 //during SSR for compress usecase we should return error to flinger
2140 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2141 pthread_mutex_unlock(&out->lock);
2142 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302143 }
2144 }
2145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002147 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002148 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002149 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2150 ret = voice_extn_compress_voip_start_output_stream(out);
2151 else
2152 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002153 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002156 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 goto exit;
2158 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002159 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2160 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302163 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2164 setChannelStatus(out, buffer, bytes);
2165 adev->mChannelStatusSet = true;
2166 }
2167
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002168 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002169 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002171 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002172 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2173 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302174 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2175 ALOGD("copl(%p):send next track params in gapless", out);
2176 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2177 out->send_next_track_params = false;
2178 out->is_compr_metadata_avail = false;
2179 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002180 }
2181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302183 if (ret < 0)
2184 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002185 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002186 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302187 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302189 } else if (-ENETRESET == ret) {
2190 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2191 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2192 pthread_mutex_unlock(&out->lock);
2193 out_standby(&out->stream.common);
2194 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302196 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002198 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 out->playback_started = 1;
2200 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002201
2202 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2203 popcount(out->channel_mask),
2204 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 }
2206 pthread_mutex_unlock(&out->lock);
2207 return ret;
2208 } else {
2209 if (out->pcm) {
2210 if (out->muted)
2211 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002214
2215 if (adev->adm_request_focus)
2216 adev->adm_request_focus(adev->adm_data, out->handle);
2217
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002218 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2219 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2220 else
2221 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002222
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302223 if (ret < 0)
2224 ret = -errno;
2225 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002226 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002227
2228 if (adev->adm_abandon_focus)
2229 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 }
2232
2233exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302234 /* ToDo: There may be a corner case when SSR happens back to back during
2235 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302236 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302237 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302238 }
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 pthread_mutex_unlock(&out->lock);
2241
2242 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002243 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002244 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302245 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302246 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302247 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302248 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302249 out->standby = true;
2250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002252 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302253 out_get_sample_rate(&out->stream.common));
2254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 }
2256 return bytes;
2257}
2258
2259static int out_get_render_position(const struct audio_stream_out *stream,
2260 uint32_t *dsp_frames)
2261{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302263 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002264
2265 if (dsp_frames == NULL)
2266 return -EINVAL;
2267
2268 *dsp_frames = 0;
2269 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002270 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 pthread_mutex_lock(&out->lock);
2272 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302273 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302275 if (ret < 0)
2276 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 ALOGVV("%s rendered frames %d sample_rate %d",
2278 __func__, *dsp_frames, out->sample_rate);
2279 }
2280 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302281 if (-ENETRESET == ret) {
2282 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2283 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2284 return -EINVAL;
2285 } else if(ret < 0) {
2286 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2287 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302288 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2289 /*
2290 * Handle corner case where compress session is closed during SSR
2291 * and timestamp is queried
2292 */
2293 ALOGE(" ERROR: sound card not active, return error");
2294 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302295 } else {
2296 return 0;
2297 }
Zhou Song32a556e2015-05-05 10:46:56 +08002298 } else if (audio_is_linear_pcm(out->format)) {
2299 *dsp_frames = out->written;
2300 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301 } else
2302 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303}
2304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002305static int out_add_audio_effect(const struct audio_stream *stream __unused,
2306 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307{
2308 return 0;
2309}
2310
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002311static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2312 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313{
2314 return 0;
2315}
2316
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002317static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2318 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319{
2320 return -EINVAL;
2321}
2322
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002323static int out_get_presentation_position(const struct audio_stream_out *stream,
2324 uint64_t *frames, struct timespec *timestamp)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002328 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002329
2330 pthread_mutex_lock(&out->lock);
2331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002332 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002333 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302334 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002335 &out->sample_rate);
2336 ALOGVV("%s rendered frames %ld sample_rate %d",
2337 __func__, dsp_frames, out->sample_rate);
2338 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302339 if (ret < 0)
2340 ret = -errno;
2341 if (-ENETRESET == ret) {
2342 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2343 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2344 ret = -EINVAL;
2345 } else
2346 ret = 0;
2347
Eric Laurent949a0892013-09-20 09:20:13 -07002348 /* this is the best we can do */
2349 clock_gettime(CLOCK_MONOTONIC, timestamp);
2350 }
2351 } else {
2352 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002353 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002354 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2355 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002356 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002357 // This adjustment accounts for buffering after app processor.
2358 // It is based on estimated DSP latency per use case, rather than exact.
2359 signed_frames -=
2360 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2361
Eric Laurent949a0892013-09-20 09:20:13 -07002362 // It would be unusual for this value to be negative, but check just in case ...
2363 if (signed_frames >= 0) {
2364 *frames = signed_frames;
2365 ret = 0;
2366 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002367 }
2368 }
2369 }
2370
2371 pthread_mutex_unlock(&out->lock);
2372
2373 return ret;
2374}
2375
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376static int out_set_callback(struct audio_stream_out *stream,
2377 stream_callback_t callback, void *cookie)
2378{
2379 struct stream_out *out = (struct stream_out *)stream;
2380
2381 ALOGV("%s", __func__);
2382 pthread_mutex_lock(&out->lock);
2383 out->offload_callback = callback;
2384 out->offload_cookie = cookie;
2385 pthread_mutex_unlock(&out->lock);
2386 return 0;
2387}
2388
2389static int out_pause(struct audio_stream_out* stream)
2390{
2391 struct stream_out *out = (struct stream_out *)stream;
2392 int status = -ENOSYS;
2393 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002394 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002395 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396 pthread_mutex_lock(&out->lock);
2397 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302398 struct audio_device *adev = out->dev;
2399 int snd_scard_state = get_snd_card_state(adev);
2400
2401 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2402 status = compress_pause(out->compr);
2403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002405
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302406 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002407 audio_extn_dts_notify_playback_state(out->usecase, 0,
2408 out->sample_rate, popcount(out->channel_mask),
2409 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 }
2411 pthread_mutex_unlock(&out->lock);
2412 }
2413 return status;
2414}
2415
2416static int out_resume(struct audio_stream_out* stream)
2417{
2418 struct stream_out *out = (struct stream_out *)stream;
2419 int status = -ENOSYS;
2420 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002421 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002422 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 status = 0;
2424 pthread_mutex_lock(&out->lock);
2425 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302426 struct audio_device *adev = out->dev;
2427 int snd_scard_state = get_snd_card_state(adev);
2428
2429 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2430 status = compress_resume(out->compr);
2431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002433
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302434 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002435 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2436 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 }
2438 pthread_mutex_unlock(&out->lock);
2439 }
2440 return status;
2441}
2442
2443static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2444{
2445 struct stream_out *out = (struct stream_out *)stream;
2446 int status = -ENOSYS;
2447 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002448 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 pthread_mutex_lock(&out->lock);
2450 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2451 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2452 else
2453 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2454 pthread_mutex_unlock(&out->lock);
2455 }
2456 return status;
2457}
2458
2459static int out_flush(struct audio_stream_out* stream)
2460{
2461 struct stream_out *out = (struct stream_out *)stream;
2462 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002463 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002464 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 pthread_mutex_lock(&out->lock);
2466 stop_compressed_output_l(out);
2467 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002468 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 return 0;
2470 }
2471 return -ENOSYS;
2472}
2473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474/** audio_stream_in implementation **/
2475static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2476{
2477 struct stream_in *in = (struct stream_in *)stream;
2478
2479 return in->config.rate;
2480}
2481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002482static int in_set_sample_rate(struct audio_stream *stream __unused,
2483 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return -ENOSYS;
2486}
2487
2488static size_t in_get_buffer_size(const struct audio_stream *stream)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002492 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2493 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002494 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2495 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002497 return in->config.period_size *
2498 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499}
2500
2501static uint32_t in_get_channels(const struct audio_stream *stream)
2502{
2503 struct stream_in *in = (struct stream_in *)stream;
2504
2505 return in->channel_mask;
2506}
2507
2508static audio_format_t in_get_format(const struct audio_stream *stream)
2509{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002510 struct stream_in *in = (struct stream_in *)stream;
2511
2512 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513}
2514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002515static int in_set_format(struct audio_stream *stream __unused,
2516 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517{
2518 return -ENOSYS;
2519}
2520
2521static int in_standby(struct audio_stream *stream)
2522{
2523 struct stream_in *in = (struct stream_in *)stream;
2524 struct audio_device *adev = in->dev;
2525 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302526 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2527 stream, in->usecase, use_case_table[in->usecase]);
2528
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002529 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2530 /* Ignore standby in case of voip call because the voip input
2531 * stream is closed in adev_close_input_stream()
2532 */
2533 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2534 return status;
2535 }
2536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002538 if (!in->standby && in->is_st_session) {
2539 ALOGD("%s: sound trigger pcm stop lab", __func__);
2540 audio_extn_sound_trigger_stop_lab(in);
2541 in->standby = 1;
2542 }
2543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002545 if (adev->adm_deregister_stream)
2546 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2547
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002548 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002550 if (in->pcm) {
2551 pcm_close(in->pcm);
2552 in->pcm = NULL;
2553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 }
2557 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002558 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 return status;
2560}
2561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002562static int in_dump(const struct audio_stream *stream __unused,
2563 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564{
2565 return 0;
2566}
2567
2568static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2569{
2570 struct stream_in *in = (struct stream_in *)stream;
2571 struct audio_device *adev = in->dev;
2572 struct str_parms *parms;
2573 char *str;
2574 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002575 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302577 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 parms = str_parms_create_str(kvpairs);
2579
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302580 if (!parms)
2581 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002583 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002584
2585 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2586 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 val = atoi(value);
2588 /* no audio source uses val == 0 */
2589 if ((in->source != val) && (val != 0)) {
2590 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002591 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2592 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2593 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2594 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002595 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002596 err = voice_extn_compress_voip_open_input_stream(in);
2597 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002598 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002599 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002600 }
2601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 }
2603 }
2604
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002605 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2606 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002608 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 in->device = val;
2610 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002611 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002612 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 }
2614 }
2615
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002616done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002618 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619
2620 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302621error:
Eric Laurent994a6932013-07-17 11:51:42 -07002622 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 return ret;
2624}
2625
2626static char* in_get_parameters(const struct audio_stream *stream,
2627 const char *keys)
2628{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002629 struct stream_in *in = (struct stream_in *)stream;
2630 struct str_parms *query = str_parms_create_str(keys);
2631 char *str;
2632 char value[256];
2633 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002634
2635 if (!query || !reply) {
2636 ALOGE("in_get_parameters: failed to create query or reply");
2637 return NULL;
2638 }
2639
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002640 ALOGV("%s: enter: keys - %s", __func__, keys);
2641
2642 voice_extn_in_get_parameters(in, query, reply);
2643
2644 str = str_parms_to_str(reply);
2645 str_parms_destroy(query);
2646 str_parms_destroy(reply);
2647
2648 ALOGV("%s: exit: returns - %s", __func__, str);
2649 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650}
2651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002652static int in_set_gain(struct audio_stream_in *stream __unused,
2653 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654{
2655 return 0;
2656}
2657
2658static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2659 size_t bytes)
2660{
2661 struct stream_in *in = (struct stream_in *)stream;
2662 struct audio_device *adev = in->dev;
2663 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302664 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302667
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002668 if (in->is_st_session) {
2669 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2670 /* Read from sound trigger HAL */
2671 audio_extn_sound_trigger_read(in, buffer, bytes);
2672 pthread_mutex_unlock(&in->lock);
2673 return bytes;
2674 }
2675
2676 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2677 ALOGD(" %s: sound card is not active/SSR state", __func__);
2678 ret= -EIO;;
2679 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302680 }
2681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002683 pthread_mutex_lock(&adev->lock);
2684 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2685 ret = voice_extn_compress_voip_start_input_stream(in);
2686 else
2687 ret = start_input_stream(in);
2688 pthread_mutex_unlock(&adev->lock);
2689 if (ret != 0) {
2690 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 }
2692 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002693 if (adev->adm_register_input_stream)
2694 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696
Naresh Tanniru4a080142015-06-15 10:35:19 -07002697 if (adev->adm_request_focus)
2698 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002701 if (audio_extn_ssr_get_enabled() &&
2702 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002703 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002704 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2705 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002706 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2707 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002708 else
2709 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302710 if (ret < 0)
2711 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 }
2713
Naresh Tanniru4a080142015-06-15 10:35:19 -07002714 if (adev->adm_abandon_focus)
2715 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 /*
2718 * Instead of writing zeroes here, we could trust the hardware
2719 * to always provide zeroes when muted.
2720 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302721 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2722 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 memset(buffer, 0, bytes);
2724
2725exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302726 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302727 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002728 if (-ENETRESET == ret)
2729 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 pthread_mutex_unlock(&in->lock);
2732
2733 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302734 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302735 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302736 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302737 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302738 in->standby = true;
2739 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302740 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002742 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002743 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302744 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 }
2746 return bytes;
2747}
2748
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002749static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750{
2751 return 0;
2752}
2753
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002754static int add_remove_audio_effect(const struct audio_stream *stream,
2755 effect_handle_t effect,
2756 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002758 struct stream_in *in = (struct stream_in *)stream;
2759 int status = 0;
2760 effect_descriptor_t desc;
2761
2762 status = (*effect)->get_descriptor(effect, &desc);
2763 if (status != 0)
2764 return status;
2765
2766 pthread_mutex_lock(&in->lock);
2767 pthread_mutex_lock(&in->dev->lock);
2768 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2769 in->enable_aec != enable &&
2770 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2771 in->enable_aec = enable;
2772 if (!in->standby)
2773 select_devices(in->dev, in->usecase);
2774 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002775 if (in->enable_ns != enable &&
2776 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2777 in->enable_ns = enable;
2778 if (!in->standby)
2779 select_devices(in->dev, in->usecase);
2780 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002781 pthread_mutex_unlock(&in->dev->lock);
2782 pthread_mutex_unlock(&in->lock);
2783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 return 0;
2785}
2786
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002787static int in_add_audio_effect(const struct audio_stream *stream,
2788 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789{
Eric Laurent994a6932013-07-17 11:51:42 -07002790 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002791 return add_remove_audio_effect(stream, effect, true);
2792}
2793
2794static int in_remove_audio_effect(const struct audio_stream *stream,
2795 effect_handle_t effect)
2796{
Eric Laurent994a6932013-07-17 11:51:42 -07002797 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002798 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799}
2800
2801static int adev_open_output_stream(struct audio_hw_device *dev,
2802 audio_io_handle_t handle,
2803 audio_devices_t devices,
2804 audio_output_flags_t flags,
2805 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002806 struct audio_stream_out **stream_out,
2807 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808{
2809 struct audio_device *adev = (struct audio_device *)dev;
2810 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002811 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002812 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302815
2816 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2817 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2818 ALOGE(" sound card is not active rejecting compress output open request");
2819 return -EINVAL;
2820 }
2821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2823
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302824 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2825 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2826 devices, flags, &out->stream);
2827
2828
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002829 if (!out) {
2830 return -ENOMEM;
2831 }
2832
Haynes Mathew George204045b2015-02-25 20:32:03 -08002833 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2834 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 if (devices == AUDIO_DEVICE_NONE)
2837 devices = AUDIO_DEVICE_OUT_SPEAKER;
2838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 out->flags = flags;
2840 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002841 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002842 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 out->sample_rate = config->sample_rate;
2844 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2845 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002846 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002847 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002848 out->non_blocking = 0;
2849 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302851 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2852 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002853 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2854 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2855
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002856 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002857 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2858 ret = read_hdmi_channel_masks(out);
2859
2860 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2861 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002862 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002863 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002864 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002865
2866 if (config->sample_rate == 0)
2867 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2868 if (config->channel_mask == 0)
2869 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2870
2871 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2874 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002876 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002878 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2879 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002880 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002881 ret = voice_extn_compress_voip_open_output_stream(out);
2882 if (ret != 0) {
2883 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2884 __func__, ret);
2885 goto error_open;
2886 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2888 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2889 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2890 ALOGE("%s: Unsupported Offload information", __func__);
2891 ret = -EINVAL;
2892 goto error_open;
2893 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002894
2895 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2896 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2897 ALOGV("read and update_pass through formats");
2898 ret = audio_extn_dolby_update_passt_formats(adev, out);
2899 if(ret != 0) {
2900 goto error_open;
2901 }
2902 if(config->offload_info.format == 0)
2903 config->offload_info.format = out->supported_formats[0];
2904 }
2905
Mingming Yin90310102013-11-13 16:57:00 -08002906 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002907 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 ALOGE("%s: Unsupported audio format", __func__);
2909 ret = -EINVAL;
2910 goto error_open;
2911 }
2912
2913 out->compr_config.codec = (struct snd_codec *)
2914 calloc(1, sizeof(struct snd_codec));
2915
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002916 if (!out->compr_config.codec) {
2917 ret = -ENOMEM;
2918 goto error_open;
2919 }
2920
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002921 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 if (config->offload_info.channel_mask)
2923 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002924 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002926 config->offload_info.channel_mask = config->channel_mask;
2927 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002928 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 out->sample_rate = config->offload_info.sample_rate;
2930
2931 out->stream.set_callback = out_set_callback;
2932 out->stream.pause = out_pause;
2933 out->stream.resume = out_resume;
2934 out->stream.drain = out_drain;
2935 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002936 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002937
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002938 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002939 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002940 audio_extn_dolby_get_snd_codec_id(adev, out,
2941 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002942 else
2943 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302945 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002946 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002947 platform_get_pcm_offload_buffer_size(&config->offload_info);
2948 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2949 out->compr_config.fragment_size =
2950 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002951 } else {
2952 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002953 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002954 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2956 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002957 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 out->compr_config.codec->bit_rate =
2959 config->offload_info.bit_rate;
2960 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002961 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302963 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002964 /*TODO: Do we need to change it for passthrough */
2965 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966
Manish Dewangan93672f12015-08-24 20:30:31 +05302967 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2968 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2969 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2970 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002971 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2972 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002973 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002974 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2975
Mingming Yin3ee55c62014-08-04 14:23:35 -07002976 if (out->bit_width == 24) {
2977 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2978 }
2979
Amit Shekhar6f461b12014-08-01 14:52:58 -07002980 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302981 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2984 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002985
Sharad Sangleb27354b2015-06-18 15:58:55 +05302986 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002987 //this flag is set from framework only if its for PCM formats
2988 //no need to check for PCM format again
2989 out->non_blocking = 0;
2990 out->use_small_bufs = true;
2991 ALOGI("Keep write blocking for small buff: non_blockling %d",
2992 out->non_blocking);
2993 }
2994
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002995 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302996 out->send_next_track_params = false;
2997 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002998 out->offload_state = OFFLOAD_STATE_IDLE;
2999 out->playback_started = 0;
3000
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003001 audio_extn_dts_create_state_notifier_node(out->usecase);
3002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 create_offload_callback_thread(out);
3004 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3005 __func__, config->offload_info.version,
3006 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003007 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003008 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003009 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3010 ret = voice_check_and_set_incall_music_usecase(adev, out);
3011 if (ret != 0) {
3012 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3013 __func__, ret);
3014 goto error_open;
3015 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003016 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3017 if (config->sample_rate == 0)
3018 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3019 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3020 config->sample_rate != 8000) {
3021 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3022 ret = -EINVAL;
3023 goto error_open;
3024 }
3025 out->sample_rate = config->sample_rate;
3026 out->config.rate = config->sample_rate;
3027 if (config->format == AUDIO_FORMAT_DEFAULT)
3028 config->format = AUDIO_FORMAT_PCM_16_BIT;
3029 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3030 config->format = AUDIO_FORMAT_PCM_16_BIT;
3031 ret = -EINVAL;
3032 goto error_open;
3033 }
3034 out->format = config->format;
3035 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3036 out->config = pcm_config_afe_proxy_playback;
3037 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003038 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3039 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3040 out->config = pcm_config_low_latency;
3041 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003042 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003043 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3045 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003047 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3048 format = AUDIO_FORMAT_PCM_16_BIT;
3049 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3050 out->config = pcm_config_deep_buffer;
3051 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003052 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003053 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003054 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003055 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003056 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003057 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059
Amit Shekhar1d896042014-10-03 13:16:09 -07003060 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3061 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003062 /* TODO remove this hardcoding and check why width is zero*/
3063 if (out->bit_width == 0)
3064 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003065 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3066 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003067 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303068 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003069 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3070 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3071 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003072 if(adev->primary_output == NULL)
3073 adev->primary_output = out;
3074 else {
3075 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003076 ret = -EEXIST;
3077 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003078 }
3079 }
3080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 /* Check if this usecase is already existing */
3082 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003083 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3084 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003087 ret = -EEXIST;
3088 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 }
3090 pthread_mutex_unlock(&adev->lock);
3091
3092 out->stream.common.get_sample_rate = out_get_sample_rate;
3093 out->stream.common.set_sample_rate = out_set_sample_rate;
3094 out->stream.common.get_buffer_size = out_get_buffer_size;
3095 out->stream.common.get_channels = out_get_channels;
3096 out->stream.common.get_format = out_get_format;
3097 out->stream.common.set_format = out_set_format;
3098 out->stream.common.standby = out_standby;
3099 out->stream.common.dump = out_dump;
3100 out->stream.common.set_parameters = out_set_parameters;
3101 out->stream.common.get_parameters = out_get_parameters;
3102 out->stream.common.add_audio_effect = out_add_audio_effect;
3103 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3104 out->stream.get_latency = out_get_latency;
3105 out->stream.set_volume = out_set_volume;
3106 out->stream.write = out_write;
3107 out->stream.get_render_position = out_get_render_position;
3108 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003109 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003112 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003113 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
3115 config->format = out->stream.common.get_format(&out->stream.common);
3116 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3117 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3118
3119 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303120 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3121 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003122
3123 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3124 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3125 popcount(out->channel_mask), out->playback_started);
3126
Eric Laurent994a6932013-07-17 11:51:42 -07003127 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003129
3130error_open:
3131 free(out);
3132 *stream_out = NULL;
3133 ALOGD("%s: exit: ret %d", __func__, ret);
3134 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135}
3136
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003137static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 struct audio_stream_out *stream)
3139{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 struct stream_out *out = (struct stream_out *)stream;
3141 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003142 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303144 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3145
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003146 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303147 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003148 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303149 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003150 if(ret != 0)
3151 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3152 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003154 out_standby(&stream->common);
3155
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003156 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003157 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003159 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 if (out->compr_config.codec != NULL)
3161 free(out->compr_config.codec);
3162 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003163
3164 if (adev->voice_tx_output == out)
3165 adev->voice_tx_output = NULL;
3166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 pthread_cond_destroy(&out->cond);
3168 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003170 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171}
3172
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003173static void close_compress_sessions(struct audio_device *adev)
3174{
Mingming Yin7b762e72015-03-04 13:47:32 -08003175 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303176 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003177 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003178 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303179
3180 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003181 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303182 if (is_offload_usecase(usecase->id)) {
3183 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003184 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3185 out = usecase->stream.out;
3186 pthread_mutex_unlock(&adev->lock);
3187 out_standby(&out->stream.common);
3188 pthread_mutex_lock(&adev->lock);
3189 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303190 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003191 }
3192 pthread_mutex_unlock(&adev->lock);
3193}
3194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3196{
3197 struct audio_device *adev = (struct audio_device *)dev;
3198 struct str_parms *parms;
3199 char *str;
3200 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003201 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003202 int ret;
3203 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003205 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303208 if (!parms)
3209 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003210 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3211 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303212 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303213 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303214 struct listnode *node;
3215 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303216 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303217 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003218 //close compress sessions on OFFLINE status
3219 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303220 } else if (strstr(snd_card_status, "ONLINE")) {
3221 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303222 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303223 if (!platform_is_acdb_initialized(adev->platform)) {
3224 ret = platform_acdb_init(adev->platform);
3225 if(ret)
3226 ALOGE("acdb initialization is failed");
3227
3228 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303229 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303230 }
3231
3232 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003233 status = voice_set_parameters(adev, parms);
3234 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003235 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003237 status = platform_set_parameters(adev->platform, parms);
3238 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003239 goto done;
3240
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3242 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003243 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3245 adev->bluetooth_nrec = true;
3246 else
3247 adev->bluetooth_nrec = false;
3248 }
3249
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003250 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3251 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3253 adev->screen_off = false;
3254 else
3255 adev->screen_off = true;
3256 }
3257
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003258 ret = str_parms_get_int(parms, "rotation", &val);
3259 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003260 bool reverse_speakers = false;
3261 switch(val) {
3262 // FIXME: note that the code below assumes that the speakers are in the correct placement
3263 // relative to the user when the device is rotated 90deg from its default rotation. This
3264 // assumption is device-specific, not platform-specific like this code.
3265 case 270:
3266 reverse_speakers = true;
3267 break;
3268 case 0:
3269 case 90:
3270 case 180:
3271 break;
3272 default:
3273 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003274 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003275 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003276 if (status == 0) {
3277 if (adev->speaker_lr_swap != reverse_speakers) {
3278 adev->speaker_lr_swap = reverse_speakers;
3279 // only update the selected device if there is active pcm playback
3280 struct audio_usecase *usecase;
3281 struct listnode *node;
3282 list_for_each(node, &adev->usecase_list) {
3283 usecase = node_to_item(node, struct audio_usecase, list);
3284 if (usecase->type == PCM_PLAYBACK) {
3285 select_devices(adev, usecase->id);
3286 break;
3287 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003288 }
3289 }
3290 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003291 }
3292
Mingming Yin514a8bc2014-07-29 15:22:21 -07003293 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3294 if (ret >= 0) {
3295 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3296 adev->bt_wb_speech_enabled = true;
3297 else
3298 adev->bt_wb_speech_enabled = false;
3299 }
3300
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003301 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3302 if (ret >= 0) {
3303 val = atoi(value);
3304 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3305 ALOGV("cache new edid");
3306 platform_cache_edid(adev->platform);
3307 }
3308 }
3309
3310 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3311 if (ret >= 0) {
3312 val = atoi(value);
3313 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3314 ALOGV("invalidate cached edid");
3315 platform_invalidate_edid(adev->platform);
3316 }
3317 }
3318
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003319 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003320
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003321done:
3322 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003323 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303324error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003325 ALOGV("%s: exit with code(%d)", __func__, status);
3326 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327}
3328
3329static char* adev_get_parameters(const struct audio_hw_device *dev,
3330 const char *keys)
3331{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003332 struct audio_device *adev = (struct audio_device *)dev;
3333 struct str_parms *reply = str_parms_create();
3334 struct str_parms *query = str_parms_create_str(keys);
3335 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303336 char value[256] = {0};
3337 int ret = 0;
3338
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003339 if (!query || !reply) {
3340 ALOGE("adev_get_parameters: failed to create query or reply");
3341 return NULL;
3342 }
3343
Naresh Tannirud7205b62014-06-20 02:54:48 +05303344 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3345 sizeof(value));
3346 if (ret >=0) {
3347 int val = 1;
3348 pthread_mutex_lock(&adev->snd_card_status.lock);
3349 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3350 val = 0;
3351 pthread_mutex_unlock(&adev->snd_card_status.lock);
3352 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3353 goto exit;
3354 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003355
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003356 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003357 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003358 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003359 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303360 pthread_mutex_unlock(&adev->lock);
3361
Naresh Tannirud7205b62014-06-20 02:54:48 +05303362exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003363 str = str_parms_to_str(reply);
3364 str_parms_destroy(query);
3365 str_parms_destroy(reply);
3366
3367 ALOGV("%s: exit: returns - %s", __func__, str);
3368 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369}
3370
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003371static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372{
3373 return 0;
3374}
3375
3376static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3377{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003378 int ret;
3379 struct audio_device *adev = (struct audio_device *)dev;
3380 pthread_mutex_lock(&adev->lock);
3381 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003382 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003383 pthread_mutex_unlock(&adev->lock);
3384 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003387static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3388 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389{
3390 return -ENOSYS;
3391}
3392
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003393static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3394 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 return -ENOSYS;
3397}
3398
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003399static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3400 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401{
3402 return -ENOSYS;
3403}
3404
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003405static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3406 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
3408 return -ENOSYS;
3409}
3410
3411static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3412{
3413 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 pthread_mutex_lock(&adev->lock);
3416 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003417 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003419 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3420 voice_is_in_call(adev)) {
3421 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303422 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003423 adev->current_call_output = NULL;
3424 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 }
3426 pthread_mutex_unlock(&adev->lock);
3427 return 0;
3428}
3429
3430static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3431{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003432 int ret;
3433
3434 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003435 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003436 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3437 pthread_mutex_unlock(&adev->lock);
3438
3439 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440}
3441
3442static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3443{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003444 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 return 0;
3446}
3447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003448static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 const struct audio_config *config)
3450{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003451 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003453 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3454 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455}
3456
3457static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003458 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 audio_devices_t devices,
3460 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003461 struct audio_stream_in **stream_in,
3462 audio_input_flags_t flags __unused,
3463 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003464 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465{
3466 struct audio_device *adev = (struct audio_device *)dev;
3467 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003468 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003469 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003470 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 *stream_in = NULL;
3473 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3474 return -EINVAL;
3475
3476 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003477
3478 if (!in) {
3479 ALOGE("failed to allocate input stream");
3480 return -ENOMEM;
3481 }
3482
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303483 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003484 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3485 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003487 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 in->stream.common.get_sample_rate = in_get_sample_rate;
3490 in->stream.common.set_sample_rate = in_set_sample_rate;
3491 in->stream.common.get_buffer_size = in_get_buffer_size;
3492 in->stream.common.get_channels = in_get_channels;
3493 in->stream.common.get_format = in_get_format;
3494 in->stream.common.set_format = in_set_format;
3495 in->stream.common.standby = in_standby;
3496 in->stream.common.dump = in_dump;
3497 in->stream.common.set_parameters = in_set_parameters;
3498 in->stream.common.get_parameters = in_get_parameters;
3499 in->stream.common.add_audio_effect = in_add_audio_effect;
3500 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3501 in->stream.set_gain = in_set_gain;
3502 in->stream.read = in_read;
3503 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3504
3505 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003506 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 in->standby = 1;
3509 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003510 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003511 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
3513 /* Update config params with the requested sample rate and channels */
3514 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003515 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3516 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3517 is_low_latency = true;
3518#if LOW_LATENCY_CAPTURE_USE_CASE
3519 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3520#endif
3521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003524 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003526 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303527 if (adev->mode != AUDIO_MODE_IN_CALL) {
3528 ret = -EINVAL;
3529 goto err_open;
3530 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003531 if (config->sample_rate == 0)
3532 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3533 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3534 config->sample_rate != 8000) {
3535 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3536 ret = -EINVAL;
3537 goto err_open;
3538 }
3539 if (config->format == AUDIO_FORMAT_DEFAULT)
3540 config->format = AUDIO_FORMAT_PCM_16_BIT;
3541 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3542 config->format = AUDIO_FORMAT_PCM_16_BIT;
3543 ret = -EINVAL;
3544 goto err_open;
3545 }
3546
3547 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3548 in->config = pcm_config_afe_proxy_record;
3549 in->config.channels = channel_count;
3550 in->config.rate = config->sample_rate;
3551 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003552 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003553 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003554 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3555 ret = -EINVAL;
3556 goto err_open;
3557 }
3558 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003559 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003560 }
Mingming Yine62d7842013-10-25 16:26:03 -07003561 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003562 audio_extn_compr_cap_format_supported(config->format) &&
3563 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003564 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003565 } else {
3566 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003567 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003568 buffer_size = get_input_buffer_size(config->sample_rate,
3569 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003570 channel_count,
3571 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003572 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003573 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3574 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3575 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3576 (in->config.rate == 8000 || in->config.rate == 16000) &&
3577 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3578 voice_extn_compress_voip_open_input_stream(in);
3579 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003580 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003582 /* This stream could be for sound trigger lab,
3583 get sound trigger pcm if present */
3584 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303585 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003588 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003589 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590
3591err_open:
3592 free(in);
3593 *stream_in = NULL;
3594 return ret;
3595}
3596
3597static void adev_close_input_stream(struct audio_hw_device *dev,
3598 struct audio_stream_in *stream)
3599{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003600 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003601 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003602 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303603
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303604 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003605
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303606 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003607 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303608
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003609 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303610 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003611 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303612 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003613 if (ret != 0)
3614 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3615 __func__, ret);
3616 } else
3617 in_standby(&stream->common);
3618
Mingming Yin7b762e72015-03-04 13:47:32 -08003619 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003620 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003621 audio_extn_ssr_deinit();
3622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623
Mingming Yine62d7842013-10-25 16:26:03 -07003624 if(audio_extn_compr_cap_enabled() &&
3625 audio_extn_compr_cap_format_supported(in->config.format))
3626 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003627
3628 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 return;
3630}
3631
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003632static int adev_dump(const audio_hw_device_t *device __unused,
3633 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634{
3635 return 0;
3636}
3637
3638static int adev_close(hw_device_t *device)
3639{
3640 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003641
3642 if (!adev)
3643 return 0;
3644
3645 pthread_mutex_lock(&adev_init_lock);
3646
3647 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003648 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003649 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003650 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003651 audio_route_free(adev->audio_route);
3652 free(adev->snd_dev_ref_cnt);
3653 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003654 if (adev->adm_deinit)
3655 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003656 free(device);
3657 adev = NULL;
3658 }
3659 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 return 0;
3662}
3663
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003664/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3665 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3666 * just that it _might_ work.
3667 */
3668static int period_size_is_plausible_for_low_latency(int period_size)
3669{
3670 switch (period_size) {
3671 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003672 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003673 case 240:
3674 case 320:
3675 case 480:
3676 return 1;
3677 default:
3678 return 0;
3679 }
3680}
3681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682static int adev_open(const hw_module_t *module, const char *name,
3683 hw_device_t **device)
3684{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003685 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003687 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3689
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003690 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003691 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003692 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003693 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003694 ALOGD("%s: returning existing instance of adev", __func__);
3695 ALOGD("%s: exit", __func__);
3696 pthread_mutex_unlock(&adev_init_lock);
3697 return 0;
3698 }
3699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 adev = calloc(1, sizeof(struct audio_device));
3701
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003702 if (!adev) {
3703 pthread_mutex_unlock(&adev_init_lock);
3704 return -ENOMEM;
3705 }
3706
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003707 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3710 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3711 adev->device.common.module = (struct hw_module_t *)module;
3712 adev->device.common.close = adev_close;
3713
3714 adev->device.init_check = adev_init_check;
3715 adev->device.set_voice_volume = adev_set_voice_volume;
3716 adev->device.set_master_volume = adev_set_master_volume;
3717 adev->device.get_master_volume = adev_get_master_volume;
3718 adev->device.set_master_mute = adev_set_master_mute;
3719 adev->device.get_master_mute = adev_get_master_mute;
3720 adev->device.set_mode = adev_set_mode;
3721 adev->device.set_mic_mute = adev_set_mic_mute;
3722 adev->device.get_mic_mute = adev_get_mic_mute;
3723 adev->device.set_parameters = adev_set_parameters;
3724 adev->device.get_parameters = adev_get_parameters;
3725 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3726 adev->device.open_output_stream = adev_open_output_stream;
3727 adev->device.close_output_stream = adev_close_output_stream;
3728 adev->device.open_input_stream = adev_open_input_stream;
3729 adev->device.close_input_stream = adev_close_input_stream;
3730 adev->device.dump = adev_dump;
3731
3732 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003734 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003735 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003738 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003739 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003740 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003741 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003742 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003743 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003744 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303745 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303746
3747 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3748 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003750 adev->platform = platform_init(adev);
3751 if (!adev->platform) {
3752 free(adev->snd_dev_ref_cnt);
3753 free(adev);
3754 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3755 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003756 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003757 return -EINVAL;
3758 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003759
Naresh Tanniru4c630392014-05-12 01:05:52 +05303760 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3761
Eric Laurentc4aef752013-09-12 17:45:53 -07003762 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3763 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3764 if (adev->visualizer_lib == NULL) {
3765 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3766 } else {
3767 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3768 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003769 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003770 "visualizer_hal_start_output");
3771 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003772 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003773 "visualizer_hal_stop_output");
3774 }
3775 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003776 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003777 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003778
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003779 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3780 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3781 if (adev->offload_effects_lib == NULL) {
3782 ALOGE("%s: DLOPEN failed for %s", __func__,
3783 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3784 } else {
3785 ALOGV("%s: DLOPEN successful for %s", __func__,
3786 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3787 adev->offload_effects_start_output =
3788 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3789 "offload_effects_bundle_hal_start_output");
3790 adev->offload_effects_stop_output =
3791 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3792 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003793 adev->offload_effects_set_hpx_state =
3794 (int (*)(bool))dlsym(adev->offload_effects_lib,
3795 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303796 adev->offload_effects_get_parameters =
3797 (void (*)(struct str_parms *, struct str_parms *))
3798 dlsym(adev->offload_effects_lib,
3799 "offload_effects_bundle_get_parameters");
3800 adev->offload_effects_set_parameters =
3801 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3802 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003803 }
3804 }
3805
Naresh Tanniru4a080142015-06-15 10:35:19 -07003806 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3807 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3808 if (adev->adm_lib == NULL) {
3809 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3810 } else {
3811 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3812 adev->adm_init = (adm_init_t)
3813 dlsym(adev->adm_lib, "adm_init");
3814 adev->adm_deinit = (adm_deinit_t)
3815 dlsym(adev->adm_lib, "adm_deinit");
3816 adev->adm_register_input_stream = (adm_register_input_stream_t)
3817 dlsym(adev->adm_lib, "adm_register_input_stream");
3818 adev->adm_register_output_stream = (adm_register_output_stream_t)
3819 dlsym(adev->adm_lib, "adm_register_output_stream");
3820 adev->adm_deregister_stream = (adm_deregister_stream_t)
3821 dlsym(adev->adm_lib, "adm_deregister_stream");
3822 adev->adm_request_focus = (adm_request_focus_t)
3823 dlsym(adev->adm_lib, "adm_request_focus");
3824 adev->adm_abandon_focus = (adm_abandon_focus_t)
3825 dlsym(adev->adm_lib, "adm_abandon_focus");
3826 }
3827 }
3828
Mingming Yin514a8bc2014-07-29 15:22:21 -07003829 adev->bt_wb_speech_enabled = false;
3830
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003831 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 *device = &adev->device.common;
3833
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003834 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3835 &adev->streams_output_cfg_list);
3836
Kiran Kandi910e1862013-10-29 13:29:42 -07003837 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003838
3839 char value[PROPERTY_VALUE_MAX];
3840 int trial;
3841 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3842 trial = atoi(value);
3843 if (period_size_is_plausible_for_low_latency(trial)) {
3844 pcm_config_low_latency.period_size = trial;
3845 pcm_config_low_latency.start_threshold = trial / 4;
3846 pcm_config_low_latency.avail_min = trial / 4;
3847 configured_low_latency_capture_period_size = trial;
3848 }
3849 }
3850 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3851 trial = atoi(value);
3852 if (period_size_is_plausible_for_low_latency(trial)) {
3853 configured_low_latency_capture_period_size = trial;
3854 }
3855 }
3856
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003857 pthread_mutex_unlock(&adev_init_lock);
3858
Naresh Tanniru4a080142015-06-15 10:35:19 -07003859 if (adev->adm_init)
3860 adev->adm_data = adev->adm_init();
3861
Eric Laurent994a6932013-07-17 11:51:42 -07003862 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 return 0;
3864}
3865
3866static struct hw_module_methods_t hal_module_methods = {
3867 .open = adev_open,
3868};
3869
3870struct audio_module HAL_MODULE_INFO_SYM = {
3871 .common = {
3872 .tag = HARDWARE_MODULE_TAG,
3873 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3874 .hal_api_version = HARDWARE_HAL_API_VERSION,
3875 .id = AUDIO_HARDWARE_MODULE_ID,
3876 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003877 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 .methods = &hal_module_methods,
3879 },
3880};