blob: 62ae7b710380ef28e0423ff48fd4ffe3540fc8be [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;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001156
1157 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158}
1159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001160/* must be called with out->lock locked */
1161static int send_offload_cmd_l(struct stream_out* out, int command)
1162{
1163 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1164
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001165 if (!cmd) {
1166 ALOGE("failed to allocate mem for command 0x%x", command);
1167 return -ENOMEM;
1168 }
1169
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001170 ALOGVV("%s %d", __func__, command);
1171
1172 cmd->cmd = command;
1173 list_add_tail(&out->offload_cmd_list, &cmd->node);
1174 pthread_cond_signal(&out->offload_cond);
1175 return 0;
1176}
1177
1178/* must be called iwth out->lock locked */
1179static void stop_compressed_output_l(struct stream_out *out)
1180{
1181 out->offload_state = OFFLOAD_STATE_IDLE;
1182 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001183 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001184 if (out->compr != NULL) {
1185 compress_stop(out->compr);
1186 while (out->offload_thread_blocked) {
1187 pthread_cond_wait(&out->cond, &out->lock);
1188 }
1189 }
1190}
1191
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001192bool is_offload_usecase(audio_usecase_t uc_id)
1193{
1194 unsigned int i;
1195 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1196 if (uc_id == offload_usecases[i])
1197 return true;
1198 }
1199 return false;
1200}
1201
1202static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1203{
1204 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1205 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1206 char value[PROPERTY_VALUE_MAX] = {0};
1207
1208 property_get("audio.offload.multiple.enabled", value, NULL);
1209 if (!(atoi(value) || !strncmp("true", value, 4)))
1210 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1211
1212 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1213 for (i = 0; i < num_usecase; i++) {
1214 if (!(adev->offload_usecases_state & (0x1<<i))) {
1215 adev->offload_usecases_state |= 0x1 << i;
1216 ret = offload_usecases[i];
1217 break;
1218 }
1219 }
1220 ALOGV("%s: offload usecase is %d", __func__, ret);
1221 return ret;
1222}
1223
1224static void free_offload_usecase(struct audio_device *adev,
1225 audio_usecase_t uc_id)
1226{
1227 unsigned int i;
1228 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1229 if (offload_usecases[i] == uc_id) {
1230 adev->offload_usecases_state &= ~(0x1<<i);
1231 break;
1232 }
1233 }
1234 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1235}
1236
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001237static void *offload_thread_loop(void *context)
1238{
1239 struct stream_out *out = (struct stream_out *) context;
1240 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001241 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001242
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001243 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1244 set_sched_policy(0, SP_FOREGROUND);
1245 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1246
1247 ALOGV("%s", __func__);
1248 pthread_mutex_lock(&out->lock);
1249 for (;;) {
1250 struct offload_cmd *cmd = NULL;
1251 stream_callback_event_t event;
1252 bool send_callback = false;
1253
1254 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1255 __func__, list_empty(&out->offload_cmd_list),
1256 out->offload_state);
1257 if (list_empty(&out->offload_cmd_list)) {
1258 ALOGV("%s SLEEPING", __func__);
1259 pthread_cond_wait(&out->offload_cond, &out->lock);
1260 ALOGV("%s RUNNING", __func__);
1261 continue;
1262 }
1263
1264 item = list_head(&out->offload_cmd_list);
1265 cmd = node_to_item(item, struct offload_cmd, node);
1266 list_remove(item);
1267
1268 ALOGVV("%s STATE %d CMD %d out->compr %p",
1269 __func__, out->offload_state, cmd->cmd, out->compr);
1270
1271 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1272 free(cmd);
1273 break;
1274 }
1275
1276 if (out->compr == NULL) {
1277 ALOGE("%s: Compress handle is NULL", __func__);
1278 pthread_cond_signal(&out->cond);
1279 continue;
1280 }
1281 out->offload_thread_blocked = true;
1282 pthread_mutex_unlock(&out->lock);
1283 send_callback = false;
1284 switch(cmd->cmd) {
1285 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001286 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001287 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 send_callback = true;
1290 event = STREAM_CBK_EVENT_WRITE_READY;
1291 break;
1292 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001293 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301294 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001295 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301296 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001297 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301298 if (ret < 0)
1299 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301300 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301301 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001302 compress_drain(out->compr);
1303 else
1304 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301305 if (ret != -ENETRESET) {
1306 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301307 pthread_mutex_lock(&out->lock);
1308 out->send_new_metadata = 1;
1309 out->send_next_track_params = true;
1310 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301311 event = STREAM_CBK_EVENT_DRAIN_READY;
1312 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1313 } else
1314 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 break;
1316 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001317 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001319 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 send_callback = true;
1321 event = STREAM_CBK_EVENT_DRAIN_READY;
1322 break;
1323 default:
1324 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1325 break;
1326 }
1327 pthread_mutex_lock(&out->lock);
1328 out->offload_thread_blocked = false;
1329 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001330 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001331 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001333 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001334 free(cmd);
1335 }
1336
1337 pthread_cond_signal(&out->cond);
1338 while (!list_empty(&out->offload_cmd_list)) {
1339 item = list_head(&out->offload_cmd_list);
1340 list_remove(item);
1341 free(node_to_item(item, struct offload_cmd, node));
1342 }
1343 pthread_mutex_unlock(&out->lock);
1344
1345 return NULL;
1346}
1347
1348static int create_offload_callback_thread(struct stream_out *out)
1349{
1350 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1351 list_init(&out->offload_cmd_list);
1352 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1353 offload_thread_loop, out);
1354 return 0;
1355}
1356
1357static int destroy_offload_callback_thread(struct stream_out *out)
1358{
1359 pthread_mutex_lock(&out->lock);
1360 stop_compressed_output_l(out);
1361 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1362
1363 pthread_mutex_unlock(&out->lock);
1364 pthread_join(out->offload_thread, (void **) NULL);
1365 pthread_cond_destroy(&out->offload_cond);
1366
1367 return 0;
1368}
1369
Eric Laurent07eeafd2013-10-06 12:52:49 -07001370static bool allow_hdmi_channel_config(struct audio_device *adev)
1371{
1372 struct listnode *node;
1373 struct audio_usecase *usecase;
1374 bool ret = true;
1375
1376 list_for_each(node, &adev->usecase_list) {
1377 usecase = node_to_item(node, struct audio_usecase, list);
1378 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1379 /*
1380 * If voice call is already existing, do not proceed further to avoid
1381 * disabling/enabling both RX and TX devices, CSD calls, etc.
1382 * Once the voice call done, the HDMI channels can be configured to
1383 * max channels of remaining use cases.
1384 */
1385 if (usecase->id == USECASE_VOICE_CALL) {
1386 ALOGD("%s: voice call is active, no change in HDMI channels",
1387 __func__);
1388 ret = false;
1389 break;
1390 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1391 ALOGD("%s: multi channel playback is active, "
1392 "no change in HDMI channels", __func__);
1393 ret = false;
1394 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001395 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001396 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001397 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1398 ", no change in HDMI channels", __func__,
1399 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001400 ret = false;
1401 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 }
1403 }
1404 }
1405 return ret;
1406}
1407
1408static int check_and_set_hdmi_channels(struct audio_device *adev,
1409 unsigned int channels)
1410{
1411 struct listnode *node;
1412 struct audio_usecase *usecase;
1413
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001414 unsigned int supported_channels = platform_edid_get_max_channels(
1415 adev->platform);
1416 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 /* Check if change in HDMI channel config is allowed */
1418 if (!allow_hdmi_channel_config(adev))
1419 return 0;
1420
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001421 if (channels > supported_channels)
1422 channels = supported_channels;
1423
Eric Laurent07eeafd2013-10-06 12:52:49 -07001424 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001425 ALOGD("%s: Requested channels are same as current channels(%d)",
1426 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 return 0;
1428 }
1429
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001430 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001432 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001433 adev->cur_hdmi_channels = channels;
1434
1435 /*
1436 * Deroute all the playback streams routed to HDMI so that
1437 * the back end is deactivated. Note that backend will not
1438 * be deactivated if any one stream is connected to it.
1439 */
1440 list_for_each(node, &adev->usecase_list) {
1441 usecase = node_to_item(node, struct audio_usecase, list);
1442 if (usecase->type == PCM_PLAYBACK &&
1443 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001444 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 }
1446 }
1447
1448 /*
1449 * Enable all the streams disabled above. Now the HDMI backend
1450 * will be activated with new channel configuration
1451 */
1452 list_for_each(node, &adev->usecase_list) {
1453 usecase = node_to_item(node, struct audio_usecase, list);
1454 if (usecase->type == PCM_PLAYBACK &&
1455 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001456 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001457 }
1458 }
1459
1460 return 0;
1461}
1462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463static int stop_output_stream(struct stream_out *out)
1464{
1465 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466 struct audio_usecase *uc_info;
1467 struct audio_device *adev = out->dev;
1468
Eric Laurent994a6932013-07-17 11:51:42 -07001469 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471 uc_info = get_usecase_from_list(adev, out->usecase);
1472 if (uc_info == NULL) {
1473 ALOGE("%s: Could not find the usecase (%d) in the list",
1474 __func__, out->usecase);
1475 return -EINVAL;
1476 }
1477
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001478 if (is_offload_usecase(out->usecase) &&
1479 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001480 if (adev->visualizer_stop_output != NULL)
1481 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001482
1483 audio_extn_dts_remove_state_notifier_node(out->usecase);
1484
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001485 if (adev->offload_effects_stop_output != NULL)
1486 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1487 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001488
Eric Laurent150dbfe2013-02-27 14:31:02 -08001489 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001490 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491
1492 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001493 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001495 list_remove(&uc_info->list);
1496 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001498 if (is_offload_usecase(out->usecase) &&
1499 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1500 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1501 ALOGV("Disable passthrough , reset mixer to pcm");
1502 /* NO_PASSTHROUGH */
1503 out->compr_config.codec->compr_passthr = 0;
1504 audio_extn_dolby_set_hdmi_config(adev, out);
1505 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1506 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001507 /* Must be called after removing the usecase from list */
1508 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1509 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1510
Eric Laurent994a6932013-07-17 11:51:42 -07001511 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 return ret;
1513}
1514
1515int start_output_stream(struct stream_out *out)
1516{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001518 int sink_channels = 0;
1519 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520 struct audio_usecase *uc_info;
1521 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301522 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001524 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1525 ret = -EINVAL;
1526 goto error_config;
1527 }
1528
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301529 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1530 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1531 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301532
Naresh Tanniru80659832014-06-04 18:17:56 +05301533 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301534 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301535 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301536 goto error_config;
1537 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301538
Eric Laurentb23d5282013-05-14 15:27:20 -07001539 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 if (out->pcm_device_id < 0) {
1541 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1542 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001543 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001544 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 }
1546
1547 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001548
1549 if (!uc_info) {
1550 ret = -ENOMEM;
1551 goto error_config;
1552 }
1553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 uc_info->id = out->usecase;
1555 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001556 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 uc_info->devices = out->devices;
1558 uc_info->in_snd_device = SND_DEVICE_NONE;
1559 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001560 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001561 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001562 if (is_offload_usecase(out->usecase)) {
1563 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001564 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1565 }
1566 }
Mingming Yin9c041392014-05-01 15:37:31 -07001567 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1568 if (!strncmp("true", prop_value, 4)) {
1569 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001570 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1571 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001572 check_and_set_hdmi_channels(adev, sink_channels);
1573 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001574 if (is_offload_usecase(out->usecase)) {
1575 unsigned int ch_count = out->compr_config.codec->ch_in;
1576 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1577 /* backend channel config for passthrough stream is stereo */
1578 ch_count = 2;
1579 check_and_set_hdmi_channels(adev, ch_count);
1580 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001581 check_and_set_hdmi_channels(adev, out->config.channels);
1582 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001583 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001584 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001585 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 select_devices(adev, out->usecase);
1588
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001589 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1590 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001591 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001592 unsigned int flags = PCM_OUT;
1593 unsigned int pcm_open_retry_count = 0;
1594 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1595 flags |= PCM_MMAP | PCM_NOIRQ;
1596 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1597 } else
1598 flags |= PCM_MONOTONIC;
1599
1600 while (1) {
1601 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1602 flags, &out->config);
1603 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1604 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1605 if (out->pcm != NULL) {
1606 pcm_close(out->pcm);
1607 out->pcm = NULL;
1608 }
1609 if (pcm_open_retry_count-- == 0) {
1610 ret = -EIO;
1611 goto error_open;
1612 }
1613 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1614 continue;
1615 }
1616 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001618
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001619 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1620 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001621
1622 ALOGV("%s: pcm_prepare start", __func__);
1623 if (pcm_is_ready(out->pcm))
1624 pcm_prepare(out->pcm);
1625
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001627 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1628 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001630 out->compr = compress_open(adev->snd_card,
1631 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001632 COMPRESS_IN, &out->compr_config);
1633 if (out->compr && !is_compress_ready(out->compr)) {
1634 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1635 compress_close(out->compr);
1636 out->compr = NULL;
1637 ret = -EIO;
1638 goto error_open;
1639 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301640 /* compress_open sends params of the track, so reset the flag here */
1641 out->is_compr_metadata_avail = false;
1642
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001643 if (out->offload_callback)
1644 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001645
Fred Oh3f43e742015-03-04 18:42:34 -08001646 /* Since small bufs uses blocking writes, a write will be blocked
1647 for the default max poll time (20s) in the event of an SSR.
1648 Reduce the poll time to observe and deal with SSR faster.
1649 */
1650 if (out->use_small_bufs) {
1651 compress_set_max_poll_wait(out->compr, 1000);
1652 }
1653
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001654 audio_extn_dts_create_state_notifier_node(out->usecase);
1655 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1656 popcount(out->channel_mask),
1657 out->playback_started);
1658
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001659#ifdef DS1_DOLBY_DDP_ENABLED
1660 if (audio_extn_is_dolby_format(out->format))
1661 audio_extn_dolby_send_ddp_endp_params(adev);
1662#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001663 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1664 if (adev->visualizer_start_output != NULL)
1665 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1666 if (adev->offload_effects_start_output != NULL)
1667 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001668 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001671
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001677error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001678 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679}
1680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681static int check_input_parameters(uint32_t sample_rate,
1682 audio_format_t format,
1683 int channel_count)
1684{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001685 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001687 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001688 !voice_extn_compress_voip_is_format_supported(format) &&
1689 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001690
1691 switch (channel_count) {
1692 case 1:
1693 case 2:
1694 case 6:
1695 break;
1696 default:
1697 ret = -EINVAL;
1698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
1700 switch (sample_rate) {
1701 case 8000:
1702 case 11025:
1703 case 12000:
1704 case 16000:
1705 case 22050:
1706 case 24000:
1707 case 32000:
1708 case 44100:
1709 case 48000:
1710 break;
1711 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001712 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 }
1714
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001715 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716}
1717
1718static size_t get_input_buffer_size(uint32_t sample_rate,
1719 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001720 int channel_count,
1721 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722{
1723 size_t size = 0;
1724
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001725 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1726 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001728 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001729 if (is_low_latency)
1730 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001731 /* ToDo: should use frame_size computed based on the format and
1732 channel_count here. */
1733 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001735 /* make sure the size is multiple of 32 bytes
1736 * At 48 kHz mono 16-bit PCM:
1737 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1738 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1739 */
1740 size += 0x1f;
1741 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001742
1743 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744}
1745
1746static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1747{
1748 struct stream_out *out = (struct stream_out *)stream;
1749
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751}
1752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001753static int out_set_sample_rate(struct audio_stream *stream __unused,
1754 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755{
1756 return -ENOSYS;
1757}
1758
1759static size_t out_get_buffer_size(const struct audio_stream *stream)
1760{
1761 struct stream_out *out = (struct stream_out *)stream;
1762
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001763 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001765 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1766 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001768 return out->config.period_size *
1769 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770}
1771
1772static uint32_t out_get_channels(const struct audio_stream *stream)
1773{
1774 struct stream_out *out = (struct stream_out *)stream;
1775
1776 return out->channel_mask;
1777}
1778
1779static audio_format_t out_get_format(const struct audio_stream *stream)
1780{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 struct stream_out *out = (struct stream_out *)stream;
1782
1783 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784}
1785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001786static int out_set_format(struct audio_stream *stream __unused,
1787 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788{
1789 return -ENOSYS;
1790}
1791
1792static int out_standby(struct audio_stream *stream)
1793{
1794 struct stream_out *out = (struct stream_out *)stream;
1795 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301797 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1798 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001799 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1800 /* Ignore standby in case of voip call because the voip output
1801 * stream is closed in adev_close_output_stream()
1802 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301803 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001804 return 0;
1805 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001809 if (adev->adm_deregister_stream)
1810 adev->adm_deregister_stream(adev->adm_data, out->handle);
1811
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001812 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001814 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001815 if (out->pcm) {
1816 pcm_close(out->pcm);
1817 out->pcm = NULL;
1818 }
1819 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001820 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301822 out->send_next_track_params = false;
1823 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001824 out->gapless_mdata.encoder_delay = 0;
1825 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001826 if (out->compr != NULL) {
1827 compress_close(out->compr);
1828 out->compr = NULL;
1829 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001830 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001832 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 }
1834 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001835 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 return 0;
1837}
1838
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001839static int out_dump(const struct audio_stream *stream __unused,
1840 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841{
1842 return 0;
1843}
1844
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001845static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1846{
1847 int ret = 0;
1848 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001849
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001851 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001852 return -EINVAL;
1853 }
1854
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301855 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001856
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1858 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301859 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1862 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301863 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 }
1865
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 ALOGV("%s new encoder delay %u and padding %u", __func__,
1867 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1868
1869 return 0;
1870}
1871
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001872static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1873{
1874 return out == adev->primary_output || out == adev->voice_tx_output;
1875}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1878{
1879 struct stream_out *out = (struct stream_out *)stream;
1880 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001881 struct audio_usecase *usecase;
1882 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 struct str_parms *parms;
1884 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001885 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001886 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887
sangwoobc677242013-08-08 16:53:43 +09001888 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301891 if (!parms)
1892 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001893 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1894 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001897 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301900 * When HDMI cable is unplugged/usb hs is disconnected the
1901 * music playback is paused and the policy manager sends routing=0
1902 * But the audioflingercontinues to write data until standby time
1903 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 * Avoid this by routing audio to speaker until standby.
1905 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301906 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1907 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001909 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1910 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 }
1912
1913 /*
1914 * select_devices() call below switches all the usecases on the same
1915 * backend to the new device. Refer to check_usecases_codec_backend() in
1916 * the select_devices(). But how do we undo this?
1917 *
1918 * For example, music playback is active on headset (deep-buffer usecase)
1919 * and if we go to ringtones and select a ringtone, low-latency usecase
1920 * will be started on headset+speaker. As we can't enable headset+speaker
1921 * and headset devices at the same time, select_devices() switches the music
1922 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1923 * So when the ringtone playback is completed, how do we undo the same?
1924 *
1925 * We are relying on the out_set_parameters() call on deep-buffer output,
1926 * once the ringtone playback is ended.
1927 * NOTE: We should not check if the current devices are same as new devices.
1928 * Because select_devices() must be called to switch back the music
1929 * playback to headset.
1930 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001931 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932 out->devices = val;
1933
1934 if (!out->standby)
1935 select_devices(adev, out->usecase);
1936
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001937 if (output_drives_call(adev, out)) {
1938 if(!voice_is_in_call(adev)) {
1939 if (adev->mode == AUDIO_MODE_IN_CALL) {
1940 adev->current_call_output = out;
1941 ret = voice_start_call(adev);
1942 }
1943 } else {
1944 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001945 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001946 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001947 }
1948 }
1949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001951 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001953
1954 if (out == adev->primary_output) {
1955 pthread_mutex_lock(&adev->lock);
1956 audio_extn_set_parameters(adev, parms);
1957 pthread_mutex_unlock(&adev->lock);
1958 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001959 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001960 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001961 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001962
1963 audio_extn_dts_create_state_notifier_node(out->usecase);
1964 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1965 popcount(out->channel_mask),
1966 out->playback_started);
1967
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001968 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001969 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301972error:
Eric Laurent994a6932013-07-17 11:51:42 -07001973 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 return ret;
1975}
1976
1977static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1978{
1979 struct stream_out *out = (struct stream_out *)stream;
1980 struct str_parms *query = str_parms_create_str(keys);
1981 char *str;
1982 char value[256];
1983 struct str_parms *reply = str_parms_create();
1984 size_t i, j;
1985 int ret;
1986 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001987
1988 if (!query || !reply) {
1989 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1990 return NULL;
1991 }
1992
Eric Laurent994a6932013-07-17 11:51:42 -07001993 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1995 if (ret >= 0) {
1996 value[0] = '\0';
1997 i = 0;
1998 while (out->supported_channel_masks[i] != 0) {
1999 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2000 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2001 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002002 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002004 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 first = false;
2006 break;
2007 }
2008 }
2009 i++;
2010 }
2011 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2012 str = str_parms_to_str(reply);
2013 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002014 voice_extn_out_get_parameters(out, query, reply);
2015 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002016 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002017 free(str);
2018 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002021
2022 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2023 if (ret >= 0) {
2024 value[0] = '\0';
2025 i = 0;
2026 first = true;
2027 while (out->supported_formats[i] != 0) {
2028 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2029 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2030 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002031 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002032 }
2033 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2034 first = false;
2035 break;
2036 }
2037 }
2038 i++;
2039 }
2040 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2041 str = str_parms_to_str(reply);
2042 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 str_parms_destroy(query);
2044 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002045 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 return str;
2047}
2048
2049static uint32_t out_get_latency(const struct audio_stream_out *stream)
2050{
2051 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002052 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Alexy Josephaa54c872014-12-03 02:46:47 -08002054 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002055 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002056 } else {
2057 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002059 }
2060
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302061 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002062 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
2065static int out_set_volume(struct audio_stream_out *stream, float left,
2066 float right)
2067{
Eric Laurenta9024de2013-04-04 09:19:12 -07002068 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 int volume[2];
2070
Eric Laurenta9024de2013-04-04 09:19:12 -07002071 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2072 /* only take left channel into account: the API is for stereo anyway */
2073 out->muted = (left == 0.0f);
2074 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002075 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002076 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2077 /*
2078 * Set mute or umute on HDMI passthrough stream.
2079 * Only take left channel into account.
2080 * Mute is 0 and unmute 1
2081 */
2082 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2083 } else {
2084 char mixer_ctl_name[128];
2085 struct audio_device *adev = out->dev;
2086 struct mixer_ctl *ctl;
2087 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002088 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002090 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2091 "Compress Playback %d Volume", pcm_device_id);
2092 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2093 if (!ctl) {
2094 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2095 __func__, mixer_ctl_name);
2096 return -EINVAL;
2097 }
2098 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2099 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2100 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2101 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002103 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 return -ENOSYS;
2106}
2107
2108static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2109 size_t bytes)
2110{
2111 struct stream_out *out = (struct stream_out *)stream;
2112 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302113 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002114 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302117
Naresh Tanniru80659832014-06-04 18:17:56 +05302118 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002119 // increase written size during SSR to avoid mismatch
2120 // with the written frames count in AF
2121 if (!is_offload_usecase(out->usecase))
2122 out->written += bytes / (out->config.channels * sizeof(short));
2123
Naresh Tanniru80659832014-06-04 18:17:56 +05302124 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302125 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302126 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002128 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302129 //during SSR for compress usecase we should return error to flinger
2130 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2131 pthread_mutex_unlock(&out->lock);
2132 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302133 }
2134 }
2135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002137 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002138 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002139 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2140 ret = voice_extn_compress_voip_start_output_stream(out);
2141 else
2142 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002143 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002146 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 goto exit;
2148 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002149 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2150 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302153 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2154 setChannelStatus(out, buffer, bytes);
2155 adev->mChannelStatusSet = true;
2156 }
2157
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002158 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002159 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002161 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2163 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302164 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2165 ALOGD("copl(%p):send next track params in gapless", out);
2166 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2167 out->send_next_track_params = false;
2168 out->is_compr_metadata_avail = false;
2169 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 }
2171
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302173 if (ret < 0)
2174 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002175 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002176 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302177 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302179 } else if (-ENETRESET == ret) {
2180 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2181 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2182 pthread_mutex_unlock(&out->lock);
2183 out_standby(&out->stream.common);
2184 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302186 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002188 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 out->playback_started = 1;
2190 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002191
2192 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2193 popcount(out->channel_mask),
2194 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 }
2196 pthread_mutex_unlock(&out->lock);
2197 return ret;
2198 } else {
2199 if (out->pcm) {
2200 if (out->muted)
2201 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002203 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002204
2205 if (adev->adm_request_focus)
2206 adev->adm_request_focus(adev->adm_data, out->handle);
2207
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002208 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2209 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2210 else
2211 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002212
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302213 if (ret < 0)
2214 ret = -errno;
2215 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002216 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002217
2218 if (adev->adm_abandon_focus)
2219 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002220 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 }
2222
2223exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302224 /* ToDo: There may be a corner case when SSR happens back to back during
2225 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302226 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302227 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302228 }
2229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 pthread_mutex_unlock(&out->lock);
2231
2232 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002233 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002234 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302235 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302236 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302237 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302238 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302239 out->standby = true;
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002242 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302243 out_get_sample_rate(&out->stream.common));
2244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 }
2246 return bytes;
2247}
2248
2249static int out_get_render_position(const struct audio_stream_out *stream,
2250 uint32_t *dsp_frames)
2251{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302253 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002254
2255 if (dsp_frames == NULL)
2256 return -EINVAL;
2257
2258 *dsp_frames = 0;
2259 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002260 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002261 pthread_mutex_lock(&out->lock);
2262 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302263 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302265 if (ret < 0)
2266 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 ALOGVV("%s rendered frames %d sample_rate %d",
2268 __func__, *dsp_frames, out->sample_rate);
2269 }
2270 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302271 if (-ENETRESET == ret) {
2272 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2273 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2274 return -EINVAL;
2275 } else if(ret < 0) {
2276 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2277 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302278 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2279 /*
2280 * Handle corner case where compress session is closed during SSR
2281 * and timestamp is queried
2282 */
2283 ALOGE(" ERROR: sound card not active, return error");
2284 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302285 } else {
2286 return 0;
2287 }
Zhou Song32a556e2015-05-05 10:46:56 +08002288 } else if (audio_is_linear_pcm(out->format)) {
2289 *dsp_frames = out->written;
2290 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 } else
2292 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293}
2294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002295static int out_add_audio_effect(const struct audio_stream *stream __unused,
2296 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297{
2298 return 0;
2299}
2300
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002301static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2302 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303{
2304 return 0;
2305}
2306
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002307static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2308 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309{
2310 return -EINVAL;
2311}
2312
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002313static int out_get_presentation_position(const struct audio_stream_out *stream,
2314 uint64_t *frames, struct timespec *timestamp)
2315{
2316 struct stream_out *out = (struct stream_out *)stream;
2317 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002318 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002319
2320 pthread_mutex_lock(&out->lock);
2321
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002322 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002323 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302324 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002325 &out->sample_rate);
2326 ALOGVV("%s rendered frames %ld sample_rate %d",
2327 __func__, dsp_frames, out->sample_rate);
2328 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302329 if (ret < 0)
2330 ret = -errno;
2331 if (-ENETRESET == ret) {
2332 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2333 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2334 ret = -EINVAL;
2335 } else
2336 ret = 0;
2337
Eric Laurent949a0892013-09-20 09:20:13 -07002338 /* this is the best we can do */
2339 clock_gettime(CLOCK_MONOTONIC, timestamp);
2340 }
2341 } else {
2342 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002343 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002344 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2345 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002346 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002347 // This adjustment accounts for buffering after app processor.
2348 // It is based on estimated DSP latency per use case, rather than exact.
2349 signed_frames -=
2350 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2351
Eric Laurent949a0892013-09-20 09:20:13 -07002352 // It would be unusual for this value to be negative, but check just in case ...
2353 if (signed_frames >= 0) {
2354 *frames = signed_frames;
2355 ret = 0;
2356 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002357 }
2358 }
2359 }
2360
2361 pthread_mutex_unlock(&out->lock);
2362
2363 return ret;
2364}
2365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366static int out_set_callback(struct audio_stream_out *stream,
2367 stream_callback_t callback, void *cookie)
2368{
2369 struct stream_out *out = (struct stream_out *)stream;
2370
2371 ALOGV("%s", __func__);
2372 pthread_mutex_lock(&out->lock);
2373 out->offload_callback = callback;
2374 out->offload_cookie = cookie;
2375 pthread_mutex_unlock(&out->lock);
2376 return 0;
2377}
2378
2379static int out_pause(struct audio_stream_out* stream)
2380{
2381 struct stream_out *out = (struct stream_out *)stream;
2382 int status = -ENOSYS;
2383 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002384 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002385 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 pthread_mutex_lock(&out->lock);
2387 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302388 struct audio_device *adev = out->dev;
2389 int snd_scard_state = get_snd_card_state(adev);
2390
2391 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2392 status = compress_pause(out->compr);
2393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002395
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302396 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002397 audio_extn_dts_notify_playback_state(out->usecase, 0,
2398 out->sample_rate, popcount(out->channel_mask),
2399 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 }
2401 pthread_mutex_unlock(&out->lock);
2402 }
2403 return status;
2404}
2405
2406static int out_resume(struct audio_stream_out* stream)
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409 int status = -ENOSYS;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002412 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 status = 0;
2414 pthread_mutex_lock(&out->lock);
2415 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302416 struct audio_device *adev = out->dev;
2417 int snd_scard_state = get_snd_card_state(adev);
2418
2419 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2420 status = compress_resume(out->compr);
2421
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002423
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302424 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002425 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2426 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 }
2428 pthread_mutex_unlock(&out->lock);
2429 }
2430 return status;
2431}
2432
2433static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 int status = -ENOSYS;
2437 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002438 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 pthread_mutex_lock(&out->lock);
2440 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2441 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2442 else
2443 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2444 pthread_mutex_unlock(&out->lock);
2445 }
2446 return status;
2447}
2448
2449static int out_flush(struct audio_stream_out* stream)
2450{
2451 struct stream_out *out = (struct stream_out *)stream;
2452 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002453 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002454 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 pthread_mutex_lock(&out->lock);
2456 stop_compressed_output_l(out);
2457 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002458 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 return 0;
2460 }
2461 return -ENOSYS;
2462}
2463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464/** audio_stream_in implementation **/
2465static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2466{
2467 struct stream_in *in = (struct stream_in *)stream;
2468
2469 return in->config.rate;
2470}
2471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002472static int in_set_sample_rate(struct audio_stream *stream __unused,
2473 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474{
2475 return -ENOSYS;
2476}
2477
2478static size_t in_get_buffer_size(const struct audio_stream *stream)
2479{
2480 struct stream_in *in = (struct stream_in *)stream;
2481
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002482 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2483 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002484 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2485 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002486
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002487 return in->config.period_size *
2488 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489}
2490
2491static uint32_t in_get_channels(const struct audio_stream *stream)
2492{
2493 struct stream_in *in = (struct stream_in *)stream;
2494
2495 return in->channel_mask;
2496}
2497
2498static audio_format_t in_get_format(const struct audio_stream *stream)
2499{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002500 struct stream_in *in = (struct stream_in *)stream;
2501
2502 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002505static int in_set_format(struct audio_stream *stream __unused,
2506 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507{
2508 return -ENOSYS;
2509}
2510
2511static int in_standby(struct audio_stream *stream)
2512{
2513 struct stream_in *in = (struct stream_in *)stream;
2514 struct audio_device *adev = in->dev;
2515 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302516 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2517 stream, in->usecase, use_case_table[in->usecase]);
2518
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002519 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2520 /* Ignore standby in case of voip call because the voip input
2521 * stream is closed in adev_close_input_stream()
2522 */
2523 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2524 return status;
2525 }
2526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002528 if (!in->standby && in->is_st_session) {
2529 ALOGD("%s: sound trigger pcm stop lab", __func__);
2530 audio_extn_sound_trigger_stop_lab(in);
2531 in->standby = 1;
2532 }
2533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002535 if (adev->adm_deregister_stream)
2536 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2537
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002538 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 if (in->pcm) {
2541 pcm_close(in->pcm);
2542 in->pcm = NULL;
2543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
2547 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002548 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 return status;
2550}
2551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002552static int in_dump(const struct audio_stream *stream __unused,
2553 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554{
2555 return 0;
2556}
2557
2558static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2559{
2560 struct stream_in *in = (struct stream_in *)stream;
2561 struct audio_device *adev = in->dev;
2562 struct str_parms *parms;
2563 char *str;
2564 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002565 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302567 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 parms = str_parms_create_str(kvpairs);
2569
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302570 if (!parms)
2571 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002573 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002574
2575 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2576 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 val = atoi(value);
2578 /* no audio source uses val == 0 */
2579 if ((in->source != val) && (val != 0)) {
2580 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002581 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2582 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2583 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2584 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002585 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002586 err = voice_extn_compress_voip_open_input_stream(in);
2587 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002588 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002589 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002590 }
2591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
2593 }
2594
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002595 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2596 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002598 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 in->device = val;
2600 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002601 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002602 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 }
2604 }
2605
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002606done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002608 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
2610 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302611error:
Eric Laurent994a6932013-07-17 11:51:42 -07002612 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 return ret;
2614}
2615
2616static char* in_get_parameters(const struct audio_stream *stream,
2617 const char *keys)
2618{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002619 struct stream_in *in = (struct stream_in *)stream;
2620 struct str_parms *query = str_parms_create_str(keys);
2621 char *str;
2622 char value[256];
2623 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002624
2625 if (!query || !reply) {
2626 ALOGE("in_get_parameters: failed to create query or reply");
2627 return NULL;
2628 }
2629
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002630 ALOGV("%s: enter: keys - %s", __func__, keys);
2631
2632 voice_extn_in_get_parameters(in, query, reply);
2633
2634 str = str_parms_to_str(reply);
2635 str_parms_destroy(query);
2636 str_parms_destroy(reply);
2637
2638 ALOGV("%s: exit: returns - %s", __func__, str);
2639 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640}
2641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002642static int in_set_gain(struct audio_stream_in *stream __unused,
2643 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return 0;
2646}
2647
2648static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2649 size_t bytes)
2650{
2651 struct stream_in *in = (struct stream_in *)stream;
2652 struct audio_device *adev = in->dev;
2653 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302654 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302657
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002658 if (in->is_st_session) {
2659 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2660 /* Read from sound trigger HAL */
2661 audio_extn_sound_trigger_read(in, buffer, bytes);
2662 pthread_mutex_unlock(&in->lock);
2663 return bytes;
2664 }
2665
2666 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2667 ALOGD(" %s: sound card is not active/SSR state", __func__);
2668 ret= -EIO;;
2669 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302670 }
2671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002673 pthread_mutex_lock(&adev->lock);
2674 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2675 ret = voice_extn_compress_voip_start_input_stream(in);
2676 else
2677 ret = start_input_stream(in);
2678 pthread_mutex_unlock(&adev->lock);
2679 if (ret != 0) {
2680 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 }
2682 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002683 if (adev->adm_register_input_stream)
2684 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686
Naresh Tanniru4a080142015-06-15 10:35:19 -07002687 if (adev->adm_request_focus)
2688 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002691 if (audio_extn_ssr_get_enabled() &&
2692 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002693 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002694 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2695 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002696 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2697 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002698 else
2699 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302700 if (ret < 0)
2701 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 }
2703
Naresh Tanniru4a080142015-06-15 10:35:19 -07002704 if (adev->adm_abandon_focus)
2705 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 /*
2708 * Instead of writing zeroes here, we could trust the hardware
2709 * to always provide zeroes when muted.
2710 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302711 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2712 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 memset(buffer, 0, bytes);
2714
2715exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302716 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302717 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002718 if (-ENETRESET == ret)
2719 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 pthread_mutex_unlock(&in->lock);
2722
2723 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302724 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302725 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302726 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302727 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302728 in->standby = true;
2729 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302730 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002732 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002733 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302734 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 }
2736 return bytes;
2737}
2738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002739static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740{
2741 return 0;
2742}
2743
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002744static int add_remove_audio_effect(const struct audio_stream *stream,
2745 effect_handle_t effect,
2746 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002748 struct stream_in *in = (struct stream_in *)stream;
2749 int status = 0;
2750 effect_descriptor_t desc;
2751
2752 status = (*effect)->get_descriptor(effect, &desc);
2753 if (status != 0)
2754 return status;
2755
2756 pthread_mutex_lock(&in->lock);
2757 pthread_mutex_lock(&in->dev->lock);
2758 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2759 in->enable_aec != enable &&
2760 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2761 in->enable_aec = enable;
2762 if (!in->standby)
2763 select_devices(in->dev, in->usecase);
2764 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002765 if (in->enable_ns != enable &&
2766 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2767 in->enable_ns = enable;
2768 if (!in->standby)
2769 select_devices(in->dev, in->usecase);
2770 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002771 pthread_mutex_unlock(&in->dev->lock);
2772 pthread_mutex_unlock(&in->lock);
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 return 0;
2775}
2776
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002777static int in_add_audio_effect(const struct audio_stream *stream,
2778 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
Eric Laurent994a6932013-07-17 11:51:42 -07002780 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002781 return add_remove_audio_effect(stream, effect, true);
2782}
2783
2784static int in_remove_audio_effect(const struct audio_stream *stream,
2785 effect_handle_t effect)
2786{
Eric Laurent994a6932013-07-17 11:51:42 -07002787 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002788 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789}
2790
2791static int adev_open_output_stream(struct audio_hw_device *dev,
2792 audio_io_handle_t handle,
2793 audio_devices_t devices,
2794 audio_output_flags_t flags,
2795 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002796 struct audio_stream_out **stream_out,
2797 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798{
2799 struct audio_device *adev = (struct audio_device *)dev;
2800 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002801 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002802 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302805
2806 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2807 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2808 ALOGE(" sound card is not active rejecting compress output open request");
2809 return -EINVAL;
2810 }
2811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2813
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302814 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2815 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2816 devices, flags, &out->stream);
2817
2818
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002819 if (!out) {
2820 return -ENOMEM;
2821 }
2822
Haynes Mathew George204045b2015-02-25 20:32:03 -08002823 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2824 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 if (devices == AUDIO_DEVICE_NONE)
2827 devices = AUDIO_DEVICE_OUT_SPEAKER;
2828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 out->flags = flags;
2830 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002831 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002832 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 out->sample_rate = config->sample_rate;
2834 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2835 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002836 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002837 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002838 out->non_blocking = 0;
2839 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302841 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2842 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002843 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2844 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2845
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002846 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002847 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2848 ret = read_hdmi_channel_masks(out);
2849
2850 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2851 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002852 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002853 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002854 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002855
2856 if (config->sample_rate == 0)
2857 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2858 if (config->channel_mask == 0)
2859 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2860
2861 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2864 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002866 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002868 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2869 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002870 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002871 ret = voice_extn_compress_voip_open_output_stream(out);
2872 if (ret != 0) {
2873 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2874 __func__, ret);
2875 goto error_open;
2876 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2878 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2879 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2880 ALOGE("%s: Unsupported Offload information", __func__);
2881 ret = -EINVAL;
2882 goto error_open;
2883 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884
2885 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2886 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2887 ALOGV("read and update_pass through formats");
2888 ret = audio_extn_dolby_update_passt_formats(adev, out);
2889 if(ret != 0) {
2890 goto error_open;
2891 }
2892 if(config->offload_info.format == 0)
2893 config->offload_info.format = out->supported_formats[0];
2894 }
2895
Mingming Yin90310102013-11-13 16:57:00 -08002896 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002897 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 ALOGE("%s: Unsupported audio format", __func__);
2899 ret = -EINVAL;
2900 goto error_open;
2901 }
2902
2903 out->compr_config.codec = (struct snd_codec *)
2904 calloc(1, sizeof(struct snd_codec));
2905
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002906 if (!out->compr_config.codec) {
2907 ret = -ENOMEM;
2908 goto error_open;
2909 }
2910
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002911 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 if (config->offload_info.channel_mask)
2913 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002914 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002916 config->offload_info.channel_mask = config->channel_mask;
2917 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002918 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 out->sample_rate = config->offload_info.sample_rate;
2920
2921 out->stream.set_callback = out_set_callback;
2922 out->stream.pause = out_pause;
2923 out->stream.resume = out_resume;
2924 out->stream.drain = out_drain;
2925 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002926 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002928 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002929 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002930 audio_extn_dolby_get_snd_codec_id(adev, out,
2931 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002932 else
2933 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302935 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002936 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002937 platform_get_pcm_offload_buffer_size(&config->offload_info);
2938 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2939 out->compr_config.fragment_size =
2940 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002941 } else {
2942 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002943 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002944 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2946 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002947 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 out->compr_config.codec->bit_rate =
2949 config->offload_info.bit_rate;
2950 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002951 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302953 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002954 /*TODO: Do we need to change it for passthrough */
2955 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956
Manish Dewangan93672f12015-08-24 20:30:31 +05302957 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2958 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2959 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2960 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002961 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2962 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002963 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002964 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2965
Mingming Yin3ee55c62014-08-04 14:23:35 -07002966 if (out->bit_width == 24) {
2967 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2968 }
2969
Amit Shekhar6f461b12014-08-01 14:52:58 -07002970 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302971 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002972
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2974 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002975
Sharad Sangleb27354b2015-06-18 15:58:55 +05302976 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002977 //this flag is set from framework only if its for PCM formats
2978 //no need to check for PCM format again
2979 out->non_blocking = 0;
2980 out->use_small_bufs = true;
2981 ALOGI("Keep write blocking for small buff: non_blockling %d",
2982 out->non_blocking);
2983 }
2984
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002985 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302986 out->send_next_track_params = false;
2987 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002988 out->offload_state = OFFLOAD_STATE_IDLE;
2989 out->playback_started = 0;
2990
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002991 audio_extn_dts_create_state_notifier_node(out->usecase);
2992
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002993 create_offload_callback_thread(out);
2994 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2995 __func__, config->offload_info.version,
2996 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002997 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002998 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002999 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3000 ret = voice_check_and_set_incall_music_usecase(adev, out);
3001 if (ret != 0) {
3002 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3003 __func__, ret);
3004 goto error_open;
3005 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003006 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3007 if (config->sample_rate == 0)
3008 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3009 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3010 config->sample_rate != 8000) {
3011 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3012 ret = -EINVAL;
3013 goto error_open;
3014 }
3015 out->sample_rate = config->sample_rate;
3016 out->config.rate = config->sample_rate;
3017 if (config->format == AUDIO_FORMAT_DEFAULT)
3018 config->format = AUDIO_FORMAT_PCM_16_BIT;
3019 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3020 config->format = AUDIO_FORMAT_PCM_16_BIT;
3021 ret = -EINVAL;
3022 goto error_open;
3023 }
3024 out->format = config->format;
3025 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3026 out->config = pcm_config_afe_proxy_playback;
3027 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003028 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3029 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3030 out->config = pcm_config_low_latency;
3031 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003032 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003033 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3035 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003037 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3038 format = AUDIO_FORMAT_PCM_16_BIT;
3039 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3040 out->config = pcm_config_deep_buffer;
3041 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003042 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003043 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003044 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003045 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003046 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003047 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 }
3049
Amit Shekhar1d896042014-10-03 13:16:09 -07003050 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3051 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003052 /* TODO remove this hardcoding and check why width is zero*/
3053 if (out->bit_width == 0)
3054 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003055 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3056 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003057 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303058 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003059 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3060 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3061 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003062 if(adev->primary_output == NULL)
3063 adev->primary_output = out;
3064 else {
3065 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003066 ret = -EEXIST;
3067 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003068 }
3069 }
3070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 /* Check if this usecase is already existing */
3072 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003073 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3074 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003077 ret = -EEXIST;
3078 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 }
3080 pthread_mutex_unlock(&adev->lock);
3081
3082 out->stream.common.get_sample_rate = out_get_sample_rate;
3083 out->stream.common.set_sample_rate = out_set_sample_rate;
3084 out->stream.common.get_buffer_size = out_get_buffer_size;
3085 out->stream.common.get_channels = out_get_channels;
3086 out->stream.common.get_format = out_get_format;
3087 out->stream.common.set_format = out_set_format;
3088 out->stream.common.standby = out_standby;
3089 out->stream.common.dump = out_dump;
3090 out->stream.common.set_parameters = out_set_parameters;
3091 out->stream.common.get_parameters = out_get_parameters;
3092 out->stream.common.add_audio_effect = out_add_audio_effect;
3093 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3094 out->stream.get_latency = out_get_latency;
3095 out->stream.set_volume = out_set_volume;
3096 out->stream.write = out_write;
3097 out->stream.get_render_position = out_get_render_position;
3098 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003099 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003102 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003103 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104
3105 config->format = out->stream.common.get_format(&out->stream.common);
3106 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3107 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3108
3109 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303110 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3111 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003112
3113 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3114 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3115 popcount(out->channel_mask), out->playback_started);
3116
Eric Laurent994a6932013-07-17 11:51:42 -07003117 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003119
3120error_open:
3121 free(out);
3122 *stream_out = NULL;
3123 ALOGD("%s: exit: ret %d", __func__, ret);
3124 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003127static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 struct audio_stream_out *stream)
3129{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 struct stream_out *out = (struct stream_out *)stream;
3131 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003132 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303134 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3135
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003136 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303137 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003138 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303139 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003140 if(ret != 0)
3141 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3142 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003144 out_standby(&stream->common);
3145
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003146 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003147 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003149 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 if (out->compr_config.codec != NULL)
3151 free(out->compr_config.codec);
3152 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003153
3154 if (adev->voice_tx_output == out)
3155 adev->voice_tx_output = NULL;
3156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157 pthread_cond_destroy(&out->cond);
3158 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003160 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161}
3162
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003163static void close_compress_sessions(struct audio_device *adev)
3164{
Mingming Yin7b762e72015-03-04 13:47:32 -08003165 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303166 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003167 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003168 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303169
3170 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003171 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303172 if (is_offload_usecase(usecase->id)) {
3173 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003174 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3175 out = usecase->stream.out;
3176 pthread_mutex_unlock(&adev->lock);
3177 out_standby(&out->stream.common);
3178 pthread_mutex_lock(&adev->lock);
3179 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303180 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003181 }
3182 pthread_mutex_unlock(&adev->lock);
3183}
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3186{
3187 struct audio_device *adev = (struct audio_device *)dev;
3188 struct str_parms *parms;
3189 char *str;
3190 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003191 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003192 int ret;
3193 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003195 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303198 if (!parms)
3199 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003200 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3201 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303202 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303203 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303204 struct listnode *node;
3205 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303206 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303207 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003208 //close compress sessions on OFFLINE status
3209 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303210 } else if (strstr(snd_card_status, "ONLINE")) {
3211 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303212 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303213 if (!platform_is_acdb_initialized(adev->platform)) {
3214 ret = platform_acdb_init(adev->platform);
3215 if(ret)
3216 ALOGE("acdb initialization is failed");
3217
3218 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303219 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303220 }
3221
3222 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003223 status = voice_set_parameters(adev, parms);
3224 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003225 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003227 status = platform_set_parameters(adev->platform, parms);
3228 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003229 goto done;
3230
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3232 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003233 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3235 adev->bluetooth_nrec = true;
3236 else
3237 adev->bluetooth_nrec = false;
3238 }
3239
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003240 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3241 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3243 adev->screen_off = false;
3244 else
3245 adev->screen_off = true;
3246 }
3247
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003248 ret = str_parms_get_int(parms, "rotation", &val);
3249 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003250 bool reverse_speakers = false;
3251 switch(val) {
3252 // FIXME: note that the code below assumes that the speakers are in the correct placement
3253 // relative to the user when the device is rotated 90deg from its default rotation. This
3254 // assumption is device-specific, not platform-specific like this code.
3255 case 270:
3256 reverse_speakers = true;
3257 break;
3258 case 0:
3259 case 90:
3260 case 180:
3261 break;
3262 default:
3263 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003264 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003265 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003266 if (status == 0) {
3267 if (adev->speaker_lr_swap != reverse_speakers) {
3268 adev->speaker_lr_swap = reverse_speakers;
3269 // only update the selected device if there is active pcm playback
3270 struct audio_usecase *usecase;
3271 struct listnode *node;
3272 list_for_each(node, &adev->usecase_list) {
3273 usecase = node_to_item(node, struct audio_usecase, list);
3274 if (usecase->type == PCM_PLAYBACK) {
3275 select_devices(adev, usecase->id);
3276 break;
3277 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003278 }
3279 }
3280 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003281 }
3282
Mingming Yin514a8bc2014-07-29 15:22:21 -07003283 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3284 if (ret >= 0) {
3285 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3286 adev->bt_wb_speech_enabled = true;
3287 else
3288 adev->bt_wb_speech_enabled = false;
3289 }
3290
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003291 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3292 if (ret >= 0) {
3293 val = atoi(value);
3294 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3295 ALOGV("cache new edid");
3296 platform_cache_edid(adev->platform);
3297 }
3298 }
3299
3300 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3301 if (ret >= 0) {
3302 val = atoi(value);
3303 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3304 ALOGV("invalidate cached edid");
3305 platform_invalidate_edid(adev->platform);
3306 }
3307 }
3308
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003309 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003310
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003311done:
3312 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003313 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303314error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003315 ALOGV("%s: exit with code(%d)", __func__, status);
3316 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
3319static char* adev_get_parameters(const struct audio_hw_device *dev,
3320 const char *keys)
3321{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003322 struct audio_device *adev = (struct audio_device *)dev;
3323 struct str_parms *reply = str_parms_create();
3324 struct str_parms *query = str_parms_create_str(keys);
3325 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303326 char value[256] = {0};
3327 int ret = 0;
3328
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003329 if (!query || !reply) {
3330 ALOGE("adev_get_parameters: failed to create query or reply");
3331 return NULL;
3332 }
3333
Naresh Tannirud7205b62014-06-20 02:54:48 +05303334 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3335 sizeof(value));
3336 if (ret >=0) {
3337 int val = 1;
3338 pthread_mutex_lock(&adev->snd_card_status.lock);
3339 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3340 val = 0;
3341 pthread_mutex_unlock(&adev->snd_card_status.lock);
3342 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3343 goto exit;
3344 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003345
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003346 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003347 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003348 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003349 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303350 pthread_mutex_unlock(&adev->lock);
3351
Naresh Tannirud7205b62014-06-20 02:54:48 +05303352exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003353 str = str_parms_to_str(reply);
3354 str_parms_destroy(query);
3355 str_parms_destroy(reply);
3356
3357 ALOGV("%s: exit: returns - %s", __func__, str);
3358 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359}
3360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003361static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 return 0;
3364}
3365
3366static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3367{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003368 int ret;
3369 struct audio_device *adev = (struct audio_device *)dev;
3370 pthread_mutex_lock(&adev->lock);
3371 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003372 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003373 pthread_mutex_unlock(&adev->lock);
3374 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003377static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3378 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379{
3380 return -ENOSYS;
3381}
3382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003383static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3384 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
3386 return -ENOSYS;
3387}
3388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3390 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 return -ENOSYS;
3393}
3394
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003395static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3396 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397{
3398 return -ENOSYS;
3399}
3400
3401static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3402{
3403 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 pthread_mutex_lock(&adev->lock);
3406 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003407 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003409 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3410 voice_is_in_call(adev)) {
3411 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303412 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003413 adev->current_call_output = NULL;
3414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 }
3416 pthread_mutex_unlock(&adev->lock);
3417 return 0;
3418}
3419
3420static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3421{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003422 int ret;
3423
3424 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003425 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003426 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3427 pthread_mutex_unlock(&adev->lock);
3428
3429 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430}
3431
3432static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3433{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003434 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 return 0;
3436}
3437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003438static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 const struct audio_config *config)
3440{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003441 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003443 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3444 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445}
3446
3447static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003448 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 audio_devices_t devices,
3450 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003451 struct audio_stream_in **stream_in,
3452 audio_input_flags_t flags __unused,
3453 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003454 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455{
3456 struct audio_device *adev = (struct audio_device *)dev;
3457 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003458 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003459 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003460 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 *stream_in = NULL;
3463 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3464 return -EINVAL;
3465
3466 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003467
3468 if (!in) {
3469 ALOGE("failed to allocate input stream");
3470 return -ENOMEM;
3471 }
3472
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303473 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003474 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3475 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003477 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 in->stream.common.get_sample_rate = in_get_sample_rate;
3480 in->stream.common.set_sample_rate = in_set_sample_rate;
3481 in->stream.common.get_buffer_size = in_get_buffer_size;
3482 in->stream.common.get_channels = in_get_channels;
3483 in->stream.common.get_format = in_get_format;
3484 in->stream.common.set_format = in_set_format;
3485 in->stream.common.standby = in_standby;
3486 in->stream.common.dump = in_dump;
3487 in->stream.common.set_parameters = in_set_parameters;
3488 in->stream.common.get_parameters = in_get_parameters;
3489 in->stream.common.add_audio_effect = in_add_audio_effect;
3490 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3491 in->stream.set_gain = in_set_gain;
3492 in->stream.read = in_read;
3493 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3494
3495 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003496 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 in->standby = 1;
3499 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003500 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003501 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
3503 /* Update config params with the requested sample rate and channels */
3504 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003505 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3506 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3507 is_low_latency = true;
3508#if LOW_LATENCY_CAPTURE_USE_CASE
3509 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3510#endif
3511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003514 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003516 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303517 if (adev->mode != AUDIO_MODE_IN_CALL) {
3518 ret = -EINVAL;
3519 goto err_open;
3520 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 if (config->sample_rate == 0)
3522 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3523 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3524 config->sample_rate != 8000) {
3525 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3526 ret = -EINVAL;
3527 goto err_open;
3528 }
3529 if (config->format == AUDIO_FORMAT_DEFAULT)
3530 config->format = AUDIO_FORMAT_PCM_16_BIT;
3531 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3532 config->format = AUDIO_FORMAT_PCM_16_BIT;
3533 ret = -EINVAL;
3534 goto err_open;
3535 }
3536
3537 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3538 in->config = pcm_config_afe_proxy_record;
3539 in->config.channels = channel_count;
3540 in->config.rate = config->sample_rate;
3541 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003542 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003543 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003544 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3545 ret = -EINVAL;
3546 goto err_open;
3547 }
3548 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003549 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003550 }
Mingming Yine62d7842013-10-25 16:26:03 -07003551 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003552 audio_extn_compr_cap_format_supported(config->format) &&
3553 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003554 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003555 } else {
3556 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003557 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003558 buffer_size = get_input_buffer_size(config->sample_rate,
3559 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003560 channel_count,
3561 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003562 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003563 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3564 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3565 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3566 (in->config.rate == 8000 || in->config.rate == 16000) &&
3567 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3568 voice_extn_compress_voip_open_input_stream(in);
3569 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003572 /* This stream could be for sound trigger lab,
3573 get sound trigger pcm if present */
3574 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303575 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003578 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003579 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580
3581err_open:
3582 free(in);
3583 *stream_in = NULL;
3584 return ret;
3585}
3586
3587static void adev_close_input_stream(struct audio_hw_device *dev,
3588 struct audio_stream_in *stream)
3589{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003590 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003591 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003592 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303593
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303594 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003595
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303596 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003597 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303598
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003599 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303600 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003601 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303602 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003603 if (ret != 0)
3604 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3605 __func__, ret);
3606 } else
3607 in_standby(&stream->common);
3608
Mingming Yin7b762e72015-03-04 13:47:32 -08003609 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003610 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003611 audio_extn_ssr_deinit();
3612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Mingming Yine62d7842013-10-25 16:26:03 -07003614 if(audio_extn_compr_cap_enabled() &&
3615 audio_extn_compr_cap_format_supported(in->config.format))
3616 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003617
3618 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 return;
3620}
3621
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003622static int adev_dump(const audio_hw_device_t *device __unused,
3623 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624{
3625 return 0;
3626}
3627
3628static int adev_close(hw_device_t *device)
3629{
3630 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003631
3632 if (!adev)
3633 return 0;
3634
3635 pthread_mutex_lock(&adev_init_lock);
3636
3637 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003638 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003639 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003640 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003641 audio_route_free(adev->audio_route);
3642 free(adev->snd_dev_ref_cnt);
3643 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003644 if (adev->adm_deinit)
3645 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003646 free(device);
3647 adev = NULL;
3648 }
3649 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 return 0;
3652}
3653
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003654/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3655 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3656 * just that it _might_ work.
3657 */
3658static int period_size_is_plausible_for_low_latency(int period_size)
3659{
3660 switch (period_size) {
3661 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003662 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003663 case 240:
3664 case 320:
3665 case 480:
3666 return 1;
3667 default:
3668 return 0;
3669 }
3670}
3671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672static int adev_open(const hw_module_t *module, const char *name,
3673 hw_device_t **device)
3674{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003675 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003677 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3679
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003680 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003681 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003682 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003683 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003684 ALOGD("%s: returning existing instance of adev", __func__);
3685 ALOGD("%s: exit", __func__);
3686 pthread_mutex_unlock(&adev_init_lock);
3687 return 0;
3688 }
3689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 adev = calloc(1, sizeof(struct audio_device));
3691
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003692 if (!adev) {
3693 pthread_mutex_unlock(&adev_init_lock);
3694 return -ENOMEM;
3695 }
3696
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003697 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3700 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3701 adev->device.common.module = (struct hw_module_t *)module;
3702 adev->device.common.close = adev_close;
3703
3704 adev->device.init_check = adev_init_check;
3705 adev->device.set_voice_volume = adev_set_voice_volume;
3706 adev->device.set_master_volume = adev_set_master_volume;
3707 adev->device.get_master_volume = adev_get_master_volume;
3708 adev->device.set_master_mute = adev_set_master_mute;
3709 adev->device.get_master_mute = adev_get_master_mute;
3710 adev->device.set_mode = adev_set_mode;
3711 adev->device.set_mic_mute = adev_set_mic_mute;
3712 adev->device.get_mic_mute = adev_get_mic_mute;
3713 adev->device.set_parameters = adev_set_parameters;
3714 adev->device.get_parameters = adev_get_parameters;
3715 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3716 adev->device.open_output_stream = adev_open_output_stream;
3717 adev->device.close_output_stream = adev_close_output_stream;
3718 adev->device.open_input_stream = adev_open_input_stream;
3719 adev->device.close_input_stream = adev_close_input_stream;
3720 adev->device.dump = adev_dump;
3721
3722 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003724 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003725 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003728 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003729 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003730 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003731 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003732 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003733 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003734 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303735 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303736
3737 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3738 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003740 adev->platform = platform_init(adev);
3741 if (!adev->platform) {
3742 free(adev->snd_dev_ref_cnt);
3743 free(adev);
3744 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3745 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003746 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003747 return -EINVAL;
3748 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003749
Naresh Tanniru4c630392014-05-12 01:05:52 +05303750 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3751
Eric Laurentc4aef752013-09-12 17:45:53 -07003752 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3753 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3754 if (adev->visualizer_lib == NULL) {
3755 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3756 } else {
3757 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3758 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003759 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003760 "visualizer_hal_start_output");
3761 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003762 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003763 "visualizer_hal_stop_output");
3764 }
3765 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003766 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003767 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003768
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003769 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3770 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3771 if (adev->offload_effects_lib == NULL) {
3772 ALOGE("%s: DLOPEN failed for %s", __func__,
3773 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3774 } else {
3775 ALOGV("%s: DLOPEN successful for %s", __func__,
3776 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3777 adev->offload_effects_start_output =
3778 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3779 "offload_effects_bundle_hal_start_output");
3780 adev->offload_effects_stop_output =
3781 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3782 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003783 adev->offload_effects_set_hpx_state =
3784 (int (*)(bool))dlsym(adev->offload_effects_lib,
3785 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303786 adev->offload_effects_get_parameters =
3787 (void (*)(struct str_parms *, struct str_parms *))
3788 dlsym(adev->offload_effects_lib,
3789 "offload_effects_bundle_get_parameters");
3790 adev->offload_effects_set_parameters =
3791 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3792 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003793 }
3794 }
3795
Naresh Tanniru4a080142015-06-15 10:35:19 -07003796 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3797 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3798 if (adev->adm_lib == NULL) {
3799 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3800 } else {
3801 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3802 adev->adm_init = (adm_init_t)
3803 dlsym(adev->adm_lib, "adm_init");
3804 adev->adm_deinit = (adm_deinit_t)
3805 dlsym(adev->adm_lib, "adm_deinit");
3806 adev->adm_register_input_stream = (adm_register_input_stream_t)
3807 dlsym(adev->adm_lib, "adm_register_input_stream");
3808 adev->adm_register_output_stream = (adm_register_output_stream_t)
3809 dlsym(adev->adm_lib, "adm_register_output_stream");
3810 adev->adm_deregister_stream = (adm_deregister_stream_t)
3811 dlsym(adev->adm_lib, "adm_deregister_stream");
3812 adev->adm_request_focus = (adm_request_focus_t)
3813 dlsym(adev->adm_lib, "adm_request_focus");
3814 adev->adm_abandon_focus = (adm_abandon_focus_t)
3815 dlsym(adev->adm_lib, "adm_abandon_focus");
3816 }
3817 }
3818
Mingming Yin514a8bc2014-07-29 15:22:21 -07003819 adev->bt_wb_speech_enabled = false;
3820
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003821 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 *device = &adev->device.common;
3823
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003824 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3825 &adev->streams_output_cfg_list);
3826
Kiran Kandi910e1862013-10-29 13:29:42 -07003827 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003828
3829 char value[PROPERTY_VALUE_MAX];
3830 int trial;
3831 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3832 trial = atoi(value);
3833 if (period_size_is_plausible_for_low_latency(trial)) {
3834 pcm_config_low_latency.period_size = trial;
3835 pcm_config_low_latency.start_threshold = trial / 4;
3836 pcm_config_low_latency.avail_min = trial / 4;
3837 configured_low_latency_capture_period_size = trial;
3838 }
3839 }
3840 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3841 trial = atoi(value);
3842 if (period_size_is_plausible_for_low_latency(trial)) {
3843 configured_low_latency_capture_period_size = trial;
3844 }
3845 }
3846
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003847 pthread_mutex_unlock(&adev_init_lock);
3848
Naresh Tanniru4a080142015-06-15 10:35:19 -07003849 if (adev->adm_init)
3850 adev->adm_data = adev->adm_init();
3851
Eric Laurent994a6932013-07-17 11:51:42 -07003852 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 return 0;
3854}
3855
3856static struct hw_module_methods_t hal_module_methods = {
3857 .open = adev_open,
3858};
3859
3860struct audio_module HAL_MODULE_INFO_SYM = {
3861 .common = {
3862 .tag = HARDWARE_MODULE_TAG,
3863 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3864 .hal_api_version = HARDWARE_HAL_API_VERSION,
3865 .id = AUDIO_HARDWARE_MODULE_ID,
3866 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003867 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 .methods = &hal_module_methods,
3869 },
3870};