blob: 512a58402acda0876cac0f198864b4584a10a345 [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;
1307 event = STREAM_CBK_EVENT_DRAIN_READY;
1308 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1309 } else
1310 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001311 break;
1312 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001313 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001315 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001316 send_callback = true;
1317 event = STREAM_CBK_EVENT_DRAIN_READY;
1318 break;
1319 default:
1320 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1321 break;
1322 }
1323 pthread_mutex_lock(&out->lock);
1324 out->offload_thread_blocked = false;
1325 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001326 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001327 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001328 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001329 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001330 free(cmd);
1331 }
1332
1333 pthread_cond_signal(&out->cond);
1334 while (!list_empty(&out->offload_cmd_list)) {
1335 item = list_head(&out->offload_cmd_list);
1336 list_remove(item);
1337 free(node_to_item(item, struct offload_cmd, node));
1338 }
1339 pthread_mutex_unlock(&out->lock);
1340
1341 return NULL;
1342}
1343
1344static int create_offload_callback_thread(struct stream_out *out)
1345{
1346 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1347 list_init(&out->offload_cmd_list);
1348 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1349 offload_thread_loop, out);
1350 return 0;
1351}
1352
1353static int destroy_offload_callback_thread(struct stream_out *out)
1354{
1355 pthread_mutex_lock(&out->lock);
1356 stop_compressed_output_l(out);
1357 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1358
1359 pthread_mutex_unlock(&out->lock);
1360 pthread_join(out->offload_thread, (void **) NULL);
1361 pthread_cond_destroy(&out->offload_cond);
1362
1363 return 0;
1364}
1365
Eric Laurent07eeafd2013-10-06 12:52:49 -07001366static bool allow_hdmi_channel_config(struct audio_device *adev)
1367{
1368 struct listnode *node;
1369 struct audio_usecase *usecase;
1370 bool ret = true;
1371
1372 list_for_each(node, &adev->usecase_list) {
1373 usecase = node_to_item(node, struct audio_usecase, list);
1374 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1375 /*
1376 * If voice call is already existing, do not proceed further to avoid
1377 * disabling/enabling both RX and TX devices, CSD calls, etc.
1378 * Once the voice call done, the HDMI channels can be configured to
1379 * max channels of remaining use cases.
1380 */
1381 if (usecase->id == USECASE_VOICE_CALL) {
1382 ALOGD("%s: voice call is active, no change in HDMI channels",
1383 __func__);
1384 ret = false;
1385 break;
1386 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1387 ALOGD("%s: multi channel playback is active, "
1388 "no change in HDMI channels", __func__);
1389 ret = false;
1390 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001391 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001392 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001393 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1394 ", no change in HDMI channels", __func__,
1395 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001396 ret = false;
1397 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001398 }
1399 }
1400 }
1401 return ret;
1402}
1403
1404static int check_and_set_hdmi_channels(struct audio_device *adev,
1405 unsigned int channels)
1406{
1407 struct listnode *node;
1408 struct audio_usecase *usecase;
1409
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001410 unsigned int supported_channels = platform_edid_get_max_channels(
1411 adev->platform);
1412 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 /* Check if change in HDMI channel config is allowed */
1414 if (!allow_hdmi_channel_config(adev))
1415 return 0;
1416
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001417 if (channels > supported_channels)
1418 channels = supported_channels;
1419
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001421 ALOGD("%s: Requested channels are same as current channels(%d)",
1422 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 return 0;
1424 }
1425
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001426 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001428 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 adev->cur_hdmi_channels = channels;
1430
1431 /*
1432 * Deroute all the playback streams routed to HDMI so that
1433 * the back end is deactivated. Note that backend will not
1434 * be deactivated if any one stream is connected to it.
1435 */
1436 list_for_each(node, &adev->usecase_list) {
1437 usecase = node_to_item(node, struct audio_usecase, list);
1438 if (usecase->type == PCM_PLAYBACK &&
1439 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001440 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001441 }
1442 }
1443
1444 /*
1445 * Enable all the streams disabled above. Now the HDMI backend
1446 * will be activated with new channel configuration
1447 */
1448 list_for_each(node, &adev->usecase_list) {
1449 usecase = node_to_item(node, struct audio_usecase, list);
1450 if (usecase->type == PCM_PLAYBACK &&
1451 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001452 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001453 }
1454 }
1455
1456 return 0;
1457}
1458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459static int stop_output_stream(struct stream_out *out)
1460{
1461 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462 struct audio_usecase *uc_info;
1463 struct audio_device *adev = out->dev;
1464
Eric Laurent994a6932013-07-17 11:51:42 -07001465 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 uc_info = get_usecase_from_list(adev, out->usecase);
1468 if (uc_info == NULL) {
1469 ALOGE("%s: Could not find the usecase (%d) in the list",
1470 __func__, out->usecase);
1471 return -EINVAL;
1472 }
1473
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001474 if (is_offload_usecase(out->usecase) &&
1475 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001476 if (adev->visualizer_stop_output != NULL)
1477 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001478
1479 audio_extn_dts_remove_state_notifier_node(out->usecase);
1480
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001481 if (adev->offload_effects_stop_output != NULL)
1482 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1483 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001484
Eric Laurent150dbfe2013-02-27 14:31:02 -08001485 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001486 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487
1488 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001489 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 list_remove(&uc_info->list);
1492 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001494 if (is_offload_usecase(out->usecase) &&
1495 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1496 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1497 ALOGV("Disable passthrough , reset mixer to pcm");
1498 /* NO_PASSTHROUGH */
1499 out->compr_config.codec->compr_passthr = 0;
1500 audio_extn_dolby_set_hdmi_config(adev, out);
1501 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1502 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 /* Must be called after removing the usecase from list */
1504 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1505 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1506
Eric Laurent994a6932013-07-17 11:51:42 -07001507 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 return ret;
1509}
1510
1511int start_output_stream(struct stream_out *out)
1512{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001514 int sink_channels = 0;
1515 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516 struct audio_usecase *uc_info;
1517 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301518 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001520 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1521 ret = -EINVAL;
1522 goto error_config;
1523 }
1524
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301525 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1526 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1527 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301528
Naresh Tanniru80659832014-06-04 18:17:56 +05301529 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301530 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301531 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301532 goto error_config;
1533 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301534
Eric Laurentb23d5282013-05-14 15:27:20 -07001535 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 if (out->pcm_device_id < 0) {
1537 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1538 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001539 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001540 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 }
1542
1543 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001544
1545 if (!uc_info) {
1546 ret = -ENOMEM;
1547 goto error_config;
1548 }
1549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 uc_info->id = out->usecase;
1551 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001552 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 uc_info->devices = out->devices;
1554 uc_info->in_snd_device = SND_DEVICE_NONE;
1555 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001556 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001557 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 if (is_offload_usecase(out->usecase)) {
1559 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1561 }
1562 }
Mingming Yin9c041392014-05-01 15:37:31 -07001563 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1564 if (!strncmp("true", prop_value, 4)) {
1565 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001566 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1567 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001568 check_and_set_hdmi_channels(adev, sink_channels);
1569 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001570 if (is_offload_usecase(out->usecase)) {
1571 unsigned int ch_count = out->compr_config.codec->ch_in;
1572 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1573 /* backend channel config for passthrough stream is stereo */
1574 ch_count = 2;
1575 check_and_set_hdmi_channels(adev, ch_count);
1576 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001577 check_and_set_hdmi_channels(adev, out->config.channels);
1578 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001579 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001580 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001581 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 select_devices(adev, out->usecase);
1584
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001585 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1586 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001587 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001588 unsigned int flags = PCM_OUT;
1589 unsigned int pcm_open_retry_count = 0;
1590 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1591 flags |= PCM_MMAP | PCM_NOIRQ;
1592 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1593 } else
1594 flags |= PCM_MONOTONIC;
1595
1596 while (1) {
1597 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1598 flags, &out->config);
1599 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1600 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1601 if (out->pcm != NULL) {
1602 pcm_close(out->pcm);
1603 out->pcm = NULL;
1604 }
1605 if (pcm_open_retry_count-- == 0) {
1606 ret = -EIO;
1607 goto error_open;
1608 }
1609 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1610 continue;
1611 }
1612 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001613 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001614
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001615 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1616 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001617
1618 ALOGV("%s: pcm_prepare start", __func__);
1619 if (pcm_is_ready(out->pcm))
1620 pcm_prepare(out->pcm);
1621
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001623 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1624 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001626 out->compr = compress_open(adev->snd_card,
1627 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001628 COMPRESS_IN, &out->compr_config);
1629 if (out->compr && !is_compress_ready(out->compr)) {
1630 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1631 compress_close(out->compr);
1632 out->compr = NULL;
1633 ret = -EIO;
1634 goto error_open;
1635 }
1636 if (out->offload_callback)
1637 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001638
Fred Oh3f43e742015-03-04 18:42:34 -08001639 /* Since small bufs uses blocking writes, a write will be blocked
1640 for the default max poll time (20s) in the event of an SSR.
1641 Reduce the poll time to observe and deal with SSR faster.
1642 */
1643 if (out->use_small_bufs) {
1644 compress_set_max_poll_wait(out->compr, 1000);
1645 }
1646
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001647 audio_extn_dts_create_state_notifier_node(out->usecase);
1648 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1649 popcount(out->channel_mask),
1650 out->playback_started);
1651
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001652#ifdef DS1_DOLBY_DDP_ENABLED
1653 if (audio_extn_is_dolby_format(out->format))
1654 audio_extn_dolby_send_ddp_endp_params(adev);
1655#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001656 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1657 if (adev->visualizer_start_output != NULL)
1658 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1659 if (adev->offload_effects_start_output != NULL)
1660 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001661 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001664
Eric Laurent994a6932013-07-17 11:51:42 -07001665 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001668error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001670error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001671 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672}
1673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674static int check_input_parameters(uint32_t sample_rate,
1675 audio_format_t format,
1676 int channel_count)
1677{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001678 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001680 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001681 !voice_extn_compress_voip_is_format_supported(format) &&
1682 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001683
1684 switch (channel_count) {
1685 case 1:
1686 case 2:
1687 case 6:
1688 break;
1689 default:
1690 ret = -EINVAL;
1691 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692
1693 switch (sample_rate) {
1694 case 8000:
1695 case 11025:
1696 case 12000:
1697 case 16000:
1698 case 22050:
1699 case 24000:
1700 case 32000:
1701 case 44100:
1702 case 48000:
1703 break;
1704 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001705 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706 }
1707
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001708 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709}
1710
1711static size_t get_input_buffer_size(uint32_t sample_rate,
1712 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001713 int channel_count,
1714 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715{
1716 size_t size = 0;
1717
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001718 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1719 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001721 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001722 if (is_low_latency)
1723 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001724 /* ToDo: should use frame_size computed based on the format and
1725 channel_count here. */
1726 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001728 /* make sure the size is multiple of 32 bytes
1729 * At 48 kHz mono 16-bit PCM:
1730 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1731 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1732 */
1733 size += 0x1f;
1734 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001735
1736 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737}
1738
1739static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1740{
1741 struct stream_out *out = (struct stream_out *)stream;
1742
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001743 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744}
1745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001746static int out_set_sample_rate(struct audio_stream *stream __unused,
1747 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748{
1749 return -ENOSYS;
1750}
1751
1752static size_t out_get_buffer_size(const struct audio_stream *stream)
1753{
1754 struct stream_out *out = (struct stream_out *)stream;
1755
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001756 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001758 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1759 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001761 return out->config.period_size *
1762 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763}
1764
1765static uint32_t out_get_channels(const struct audio_stream *stream)
1766{
1767 struct stream_out *out = (struct stream_out *)stream;
1768
1769 return out->channel_mask;
1770}
1771
1772static audio_format_t out_get_format(const struct audio_stream *stream)
1773{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 struct stream_out *out = (struct stream_out *)stream;
1775
1776 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777}
1778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001779static int out_set_format(struct audio_stream *stream __unused,
1780 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781{
1782 return -ENOSYS;
1783}
1784
1785static int out_standby(struct audio_stream *stream)
1786{
1787 struct stream_out *out = (struct stream_out *)stream;
1788 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301790 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1791 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001792 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1793 /* Ignore standby in case of voip call because the voip output
1794 * stream is closed in adev_close_output_stream()
1795 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301796 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001797 return 0;
1798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001802 if (adev->adm_deregister_stream)
1803 adev->adm_deregister_stream(adev->adm_data, out->handle);
1804
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001805 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001807 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 if (out->pcm) {
1809 pcm_close(out->pcm);
1810 out->pcm = NULL;
1811 }
1812 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001813 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001814 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001815 out->gapless_mdata.encoder_delay = 0;
1816 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 if (out->compr != NULL) {
1818 compress_close(out->compr);
1819 out->compr = NULL;
1820 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001821 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001823 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 }
1825 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001826 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 return 0;
1828}
1829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001830static int out_dump(const struct audio_stream *stream __unused,
1831 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832{
1833 return 0;
1834}
1835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1837{
1838 int ret = 0;
1839 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301840 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001841
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001842 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001843 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 return -EINVAL;
1845 }
1846
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301847 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001848
Yadav Anamikafbcef792015-08-19 16:15:00 +05301849 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1850 if(ret >= 0)
1851 is_meta_data_params = true;
1852 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1853 if(ret >= 0)
1854 is_meta_data_params = true;
1855 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1856 if(ret >= 0)
1857 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001858 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1859 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301860 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301861 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001863 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1864 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301865 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301866 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 }
1868
Yadav Anamikafbcef792015-08-19 16:15:00 +05301869 if(!is_meta_data_params) {
1870 ALOGV("%s: Not gapless meta data params", __func__);
1871 return 0;
1872 }
1873 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 ALOGV("%s new encoder delay %u and padding %u", __func__,
1875 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1876
1877 return 0;
1878}
1879
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001880static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1881{
1882 return out == adev->primary_output || out == adev->voice_tx_output;
1883}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1886{
1887 struct stream_out *out = (struct stream_out *)stream;
1888 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001889 struct audio_usecase *usecase;
1890 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 struct str_parms *parms;
1892 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001893 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001894 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895
sangwoobc677242013-08-08 16:53:43 +09001896 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001897 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301899 if (!parms)
1900 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001901 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1902 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301908 * When HDMI cable is unplugged/usb hs is disconnected the
1909 * music playback is paused and the policy manager sends routing=0
1910 * But the audioflingercontinues to write data until standby time
1911 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912 * Avoid this by routing audio to speaker until standby.
1913 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301914 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1915 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001917 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1918 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 }
1920
1921 /*
1922 * select_devices() call below switches all the usecases on the same
1923 * backend to the new device. Refer to check_usecases_codec_backend() in
1924 * the select_devices(). But how do we undo this?
1925 *
1926 * For example, music playback is active on headset (deep-buffer usecase)
1927 * and if we go to ringtones and select a ringtone, low-latency usecase
1928 * will be started on headset+speaker. As we can't enable headset+speaker
1929 * and headset devices at the same time, select_devices() switches the music
1930 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1931 * So when the ringtone playback is completed, how do we undo the same?
1932 *
1933 * We are relying on the out_set_parameters() call on deep-buffer output,
1934 * once the ringtone playback is ended.
1935 * NOTE: We should not check if the current devices are same as new devices.
1936 * Because select_devices() must be called to switch back the music
1937 * playback to headset.
1938 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001939 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 out->devices = val;
1941
1942 if (!out->standby)
1943 select_devices(adev, out->usecase);
1944
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001945 if (output_drives_call(adev, out)) {
1946 if(!voice_is_in_call(adev)) {
1947 if (adev->mode == AUDIO_MODE_IN_CALL) {
1948 adev->current_call_output = out;
1949 ret = voice_start_call(adev);
1950 }
1951 } else {
1952 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001953 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001954 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001955 }
1956 }
1957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001959 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001961
1962 if (out == adev->primary_output) {
1963 pthread_mutex_lock(&adev->lock);
1964 audio_extn_set_parameters(adev, parms);
1965 pthread_mutex_unlock(&adev->lock);
1966 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001967 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001968 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001969 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001970
1971 audio_extn_dts_create_state_notifier_node(out->usecase);
1972 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1973 popcount(out->channel_mask),
1974 out->playback_started);
1975
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001976 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001977 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301980error:
Eric Laurent994a6932013-07-17 11:51:42 -07001981 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 return ret;
1983}
1984
1985static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1986{
1987 struct stream_out *out = (struct stream_out *)stream;
1988 struct str_parms *query = str_parms_create_str(keys);
1989 char *str;
1990 char value[256];
1991 struct str_parms *reply = str_parms_create();
1992 size_t i, j;
1993 int ret;
1994 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001995
1996 if (!query || !reply) {
1997 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1998 return NULL;
1999 }
2000
Eric Laurent994a6932013-07-17 11:51:42 -07002001 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2003 if (ret >= 0) {
2004 value[0] = '\0';
2005 i = 0;
2006 while (out->supported_channel_masks[i] != 0) {
2007 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2008 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2009 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002010 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002012 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 first = false;
2014 break;
2015 }
2016 }
2017 i++;
2018 }
2019 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2020 str = str_parms_to_str(reply);
2021 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002022 voice_extn_out_get_parameters(out, query, reply);
2023 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002024 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002025 free(str);
2026 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002029
2030 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2031 if (ret >= 0) {
2032 value[0] = '\0';
2033 i = 0;
2034 first = true;
2035 while (out->supported_formats[i] != 0) {
2036 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2037 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2038 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002039 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002040 }
2041 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2042 first = false;
2043 break;
2044 }
2045 }
2046 i++;
2047 }
2048 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2049 str = str_parms_to_str(reply);
2050 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 str_parms_destroy(query);
2052 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return str;
2055}
2056
2057static uint32_t out_get_latency(const struct audio_stream_out *stream)
2058{
2059 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002060 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061
Alexy Josephaa54c872014-12-03 02:46:47 -08002062 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002063 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002064 } else {
2065 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002067 }
2068
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302069 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002070 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071}
2072
2073static int out_set_volume(struct audio_stream_out *stream, float left,
2074 float right)
2075{
Eric Laurenta9024de2013-04-04 09:19:12 -07002076 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 int volume[2];
2078
Eric Laurenta9024de2013-04-04 09:19:12 -07002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2080 /* only take left channel into account: the API is for stereo anyway */
2081 out->muted = (left == 0.0f);
2082 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002083 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002084 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2085 /*
2086 * Set mute or umute on HDMI passthrough stream.
2087 * Only take left channel into account.
2088 * Mute is 0 and unmute 1
2089 */
2090 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2091 } else {
2092 char mixer_ctl_name[128];
2093 struct audio_device *adev = out->dev;
2094 struct mixer_ctl *ctl;
2095 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002096 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002098 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2099 "Compress Playback %d Volume", pcm_device_id);
2100 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2101 if (!ctl) {
2102 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2103 __func__, mixer_ctl_name);
2104 return -EINVAL;
2105 }
2106 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2107 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2108 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2109 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002111 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 return -ENOSYS;
2114}
2115
2116static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2117 size_t bytes)
2118{
2119 struct stream_out *out = (struct stream_out *)stream;
2120 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302121 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002122 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302125
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002127 // increase written size during SSR to avoid mismatch
2128 // with the written frames count in AF
2129 if (!is_offload_usecase(out->usecase))
2130 out->written += bytes / (out->config.channels * sizeof(short));
2131
Naresh Tanniru80659832014-06-04 18:17:56 +05302132 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302133 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302134 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302135 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002136 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302137 //during SSR for compress usecase we should return error to flinger
2138 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2139 pthread_mutex_unlock(&out->lock);
2140 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302141 }
2142 }
2143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002145 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002146 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002147 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2148 ret = voice_extn_compress_voip_start_output_stream(out);
2149 else
2150 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002151 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002154 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 goto exit;
2156 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002157 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2158 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302161 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2162 setChannelStatus(out, buffer, bytes);
2163 adev->mChannelStatusSet = true;
2164 }
2165
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002166 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002167 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002169 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2171 out->send_new_metadata = 0;
2172 }
2173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302175 if (ret < 0)
2176 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002177 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002178 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302179 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302181 } else if (-ENETRESET == ret) {
2182 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2184 pthread_mutex_unlock(&out->lock);
2185 out_standby(&out->stream.common);
2186 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002190 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 out->playback_started = 1;
2192 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002193
2194 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2195 popcount(out->channel_mask),
2196 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
2198 pthread_mutex_unlock(&out->lock);
2199 return ret;
2200 } else {
2201 if (out->pcm) {
2202 if (out->muted)
2203 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002204
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002206
2207 if (adev->adm_request_focus)
2208 adev->adm_request_focus(adev->adm_data, out->handle);
2209
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002210 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2211 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2212 else
2213 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002214
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302215 if (ret < 0)
2216 ret = -errno;
2217 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002218 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002219
2220 if (adev->adm_abandon_focus)
2221 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 }
2224
2225exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302226 /* ToDo: There may be a corner case when SSR happens back to back during
2227 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302228 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302230 }
2231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 pthread_mutex_unlock(&out->lock);
2233
2234 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002235 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002236 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302237 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302238 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302239 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302240 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302241 out->standby = true;
2242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002244 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302245 out_get_sample_rate(&out->stream.common));
2246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 }
2248 return bytes;
2249}
2250
2251static int out_get_render_position(const struct audio_stream_out *stream,
2252 uint32_t *dsp_frames)
2253{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302255 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002256
2257 if (dsp_frames == NULL)
2258 return -EINVAL;
2259
2260 *dsp_frames = 0;
2261 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002262 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 pthread_mutex_lock(&out->lock);
2264 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302265 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302267 if (ret < 0)
2268 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 ALOGVV("%s rendered frames %d sample_rate %d",
2270 __func__, *dsp_frames, out->sample_rate);
2271 }
2272 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302273 if (-ENETRESET == ret) {
2274 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2275 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2276 return -EINVAL;
2277 } else if(ret < 0) {
2278 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2279 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302280 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2281 /*
2282 * Handle corner case where compress session is closed during SSR
2283 * and timestamp is queried
2284 */
2285 ALOGE(" ERROR: sound card not active, return error");
2286 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302287 } else {
2288 return 0;
2289 }
Zhou Song32a556e2015-05-05 10:46:56 +08002290 } else if (audio_is_linear_pcm(out->format)) {
2291 *dsp_frames = out->written;
2292 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 } else
2294 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295}
2296
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002297static int out_add_audio_effect(const struct audio_stream *stream __unused,
2298 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299{
2300 return 0;
2301}
2302
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002303static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2304 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305{
2306 return 0;
2307}
2308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002309static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2310 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311{
2312 return -EINVAL;
2313}
2314
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002315static int out_get_presentation_position(const struct audio_stream_out *stream,
2316 uint64_t *frames, struct timespec *timestamp)
2317{
2318 struct stream_out *out = (struct stream_out *)stream;
2319 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002320 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002321
2322 pthread_mutex_lock(&out->lock);
2323
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002324 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002325 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302326 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002327 &out->sample_rate);
2328 ALOGVV("%s rendered frames %ld sample_rate %d",
2329 __func__, dsp_frames, out->sample_rate);
2330 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302331 if (ret < 0)
2332 ret = -errno;
2333 if (-ENETRESET == ret) {
2334 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2335 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2336 ret = -EINVAL;
2337 } else
2338 ret = 0;
2339
Eric Laurent949a0892013-09-20 09:20:13 -07002340 /* this is the best we can do */
2341 clock_gettime(CLOCK_MONOTONIC, timestamp);
2342 }
2343 } else {
2344 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002345 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002346 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2347 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002348 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002349 // This adjustment accounts for buffering after app processor.
2350 // It is based on estimated DSP latency per use case, rather than exact.
2351 signed_frames -=
2352 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2353
Eric Laurent949a0892013-09-20 09:20:13 -07002354 // It would be unusual for this value to be negative, but check just in case ...
2355 if (signed_frames >= 0) {
2356 *frames = signed_frames;
2357 ret = 0;
2358 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002359 }
2360 }
2361 }
2362
2363 pthread_mutex_unlock(&out->lock);
2364
2365 return ret;
2366}
2367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368static int out_set_callback(struct audio_stream_out *stream,
2369 stream_callback_t callback, void *cookie)
2370{
2371 struct stream_out *out = (struct stream_out *)stream;
2372
2373 ALOGV("%s", __func__);
2374 pthread_mutex_lock(&out->lock);
2375 out->offload_callback = callback;
2376 out->offload_cookie = cookie;
2377 pthread_mutex_unlock(&out->lock);
2378 return 0;
2379}
2380
2381static int out_pause(struct audio_stream_out* stream)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384 int status = -ENOSYS;
2385 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002386 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002387 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 pthread_mutex_lock(&out->lock);
2389 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302390 struct audio_device *adev = out->dev;
2391 int snd_scard_state = get_snd_card_state(adev);
2392
2393 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2394 status = compress_pause(out->compr);
2395
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002397
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302398 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399 audio_extn_dts_notify_playback_state(out->usecase, 0,
2400 out->sample_rate, popcount(out->channel_mask),
2401 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 }
2403 pthread_mutex_unlock(&out->lock);
2404 }
2405 return status;
2406}
2407
2408static int out_resume(struct audio_stream_out* stream)
2409{
2410 struct stream_out *out = (struct stream_out *)stream;
2411 int status = -ENOSYS;
2412 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002413 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002414 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 status = 0;
2416 pthread_mutex_lock(&out->lock);
2417 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302418 struct audio_device *adev = out->dev;
2419 int snd_scard_state = get_snd_card_state(adev);
2420
2421 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2422 status = compress_resume(out->compr);
2423
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002425
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302426 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002427 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2428 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429 }
2430 pthread_mutex_unlock(&out->lock);
2431 }
2432 return status;
2433}
2434
2435static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2436{
2437 struct stream_out *out = (struct stream_out *)stream;
2438 int status = -ENOSYS;
2439 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002440 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 pthread_mutex_lock(&out->lock);
2442 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2443 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2444 else
2445 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2446 pthread_mutex_unlock(&out->lock);
2447 }
2448 return status;
2449}
2450
2451static int out_flush(struct audio_stream_out* stream)
2452{
2453 struct stream_out *out = (struct stream_out *)stream;
2454 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002455 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002456 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 pthread_mutex_lock(&out->lock);
2458 stop_compressed_output_l(out);
2459 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002460 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 return 0;
2462 }
2463 return -ENOSYS;
2464}
2465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466/** audio_stream_in implementation **/
2467static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2468{
2469 struct stream_in *in = (struct stream_in *)stream;
2470
2471 return in->config.rate;
2472}
2473
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002474static int in_set_sample_rate(struct audio_stream *stream __unused,
2475 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476{
2477 return -ENOSYS;
2478}
2479
2480static size_t in_get_buffer_size(const struct audio_stream *stream)
2481{
2482 struct stream_in *in = (struct stream_in *)stream;
2483
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002484 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2485 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002486 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2487 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002488
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002489 return in->config.period_size *
2490 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491}
2492
2493static uint32_t in_get_channels(const struct audio_stream *stream)
2494{
2495 struct stream_in *in = (struct stream_in *)stream;
2496
2497 return in->channel_mask;
2498}
2499
2500static audio_format_t in_get_format(const struct audio_stream *stream)
2501{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002502 struct stream_in *in = (struct stream_in *)stream;
2503
2504 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505}
2506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002507static int in_set_format(struct audio_stream *stream __unused,
2508 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509{
2510 return -ENOSYS;
2511}
2512
2513static int in_standby(struct audio_stream *stream)
2514{
2515 struct stream_in *in = (struct stream_in *)stream;
2516 struct audio_device *adev = in->dev;
2517 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302518 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2519 stream, in->usecase, use_case_table[in->usecase]);
2520
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002521 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2522 /* Ignore standby in case of voip call because the voip input
2523 * stream is closed in adev_close_input_stream()
2524 */
2525 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2526 return status;
2527 }
2528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002530 if (!in->standby && in->is_st_session) {
2531 ALOGD("%s: sound trigger pcm stop lab", __func__);
2532 audio_extn_sound_trigger_stop_lab(in);
2533 in->standby = 1;
2534 }
2535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002537 if (adev->adm_deregister_stream)
2538 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2539
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002540 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002542 if (in->pcm) {
2543 pcm_close(in->pcm);
2544 in->pcm = NULL;
2545 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 }
2549 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002550 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 return status;
2552}
2553
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002554static int in_dump(const struct audio_stream *stream __unused,
2555 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556{
2557 return 0;
2558}
2559
2560static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2561{
2562 struct stream_in *in = (struct stream_in *)stream;
2563 struct audio_device *adev = in->dev;
2564 struct str_parms *parms;
2565 char *str;
2566 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002567 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302569 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 parms = str_parms_create_str(kvpairs);
2571
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302572 if (!parms)
2573 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002575 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002576
2577 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2578 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 val = atoi(value);
2580 /* no audio source uses val == 0 */
2581 if ((in->source != val) && (val != 0)) {
2582 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002583 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2584 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2585 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2586 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002587 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002588 err = voice_extn_compress_voip_open_input_stream(in);
2589 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002590 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002591 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002592 }
2593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
2595 }
2596
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002597 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2598 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002600 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 in->device = val;
2602 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002603 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002604 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 }
2606 }
2607
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002608done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002610 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611
2612 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302613error:
Eric Laurent994a6932013-07-17 11:51:42 -07002614 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 return ret;
2616}
2617
2618static char* in_get_parameters(const struct audio_stream *stream,
2619 const char *keys)
2620{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002621 struct stream_in *in = (struct stream_in *)stream;
2622 struct str_parms *query = str_parms_create_str(keys);
2623 char *str;
2624 char value[256];
2625 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002626
2627 if (!query || !reply) {
2628 ALOGE("in_get_parameters: failed to create query or reply");
2629 return NULL;
2630 }
2631
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002632 ALOGV("%s: enter: keys - %s", __func__, keys);
2633
2634 voice_extn_in_get_parameters(in, query, reply);
2635
2636 str = str_parms_to_str(reply);
2637 str_parms_destroy(query);
2638 str_parms_destroy(reply);
2639
2640 ALOGV("%s: exit: returns - %s", __func__, str);
2641 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642}
2643
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002644static int in_set_gain(struct audio_stream_in *stream __unused,
2645 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646{
2647 return 0;
2648}
2649
2650static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2651 size_t bytes)
2652{
2653 struct stream_in *in = (struct stream_in *)stream;
2654 struct audio_device *adev = in->dev;
2655 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302656 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302659
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002660 if (in->is_st_session) {
2661 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2662 /* Read from sound trigger HAL */
2663 audio_extn_sound_trigger_read(in, buffer, bytes);
2664 pthread_mutex_unlock(&in->lock);
2665 return bytes;
2666 }
2667
2668 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2669 ALOGD(" %s: sound card is not active/SSR state", __func__);
2670 ret= -EIO;;
2671 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302672 }
2673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002675 pthread_mutex_lock(&adev->lock);
2676 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2677 ret = voice_extn_compress_voip_start_input_stream(in);
2678 else
2679 ret = start_input_stream(in);
2680 pthread_mutex_unlock(&adev->lock);
2681 if (ret != 0) {
2682 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 }
2684 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002685 if (adev->adm_register_input_stream)
2686 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688
Naresh Tanniru4a080142015-06-15 10:35:19 -07002689 if (adev->adm_request_focus)
2690 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002693 if (audio_extn_ssr_get_enabled() &&
2694 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002695 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002696 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2697 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002698 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2699 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002700 else
2701 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302702 if (ret < 0)
2703 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
2705
Naresh Tanniru4a080142015-06-15 10:35:19 -07002706 if (adev->adm_abandon_focus)
2707 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 /*
2710 * Instead of writing zeroes here, we could trust the hardware
2711 * to always provide zeroes when muted.
2712 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302713 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2714 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 memset(buffer, 0, bytes);
2716
2717exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302718 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302719 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002720 if (-ENETRESET == ret)
2721 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 pthread_mutex_unlock(&in->lock);
2724
2725 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302726 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302727 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302728 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302729 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302730 in->standby = true;
2731 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302732 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002734 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002735 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302736 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 }
2738 return bytes;
2739}
2740
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002741static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742{
2743 return 0;
2744}
2745
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002746static int add_remove_audio_effect(const struct audio_stream *stream,
2747 effect_handle_t effect,
2748 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002750 struct stream_in *in = (struct stream_in *)stream;
2751 int status = 0;
2752 effect_descriptor_t desc;
2753
2754 status = (*effect)->get_descriptor(effect, &desc);
2755 if (status != 0)
2756 return status;
2757
2758 pthread_mutex_lock(&in->lock);
2759 pthread_mutex_lock(&in->dev->lock);
2760 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2761 in->enable_aec != enable &&
2762 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2763 in->enable_aec = enable;
2764 if (!in->standby)
2765 select_devices(in->dev, in->usecase);
2766 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002767 if (in->enable_ns != enable &&
2768 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2769 in->enable_ns = enable;
2770 if (!in->standby)
2771 select_devices(in->dev, in->usecase);
2772 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002773 pthread_mutex_unlock(&in->dev->lock);
2774 pthread_mutex_unlock(&in->lock);
2775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 return 0;
2777}
2778
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002779static int in_add_audio_effect(const struct audio_stream *stream,
2780 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781{
Eric Laurent994a6932013-07-17 11:51:42 -07002782 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002783 return add_remove_audio_effect(stream, effect, true);
2784}
2785
2786static int in_remove_audio_effect(const struct audio_stream *stream,
2787 effect_handle_t effect)
2788{
Eric Laurent994a6932013-07-17 11:51:42 -07002789 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002790 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791}
2792
2793static int adev_open_output_stream(struct audio_hw_device *dev,
2794 audio_io_handle_t handle,
2795 audio_devices_t devices,
2796 audio_output_flags_t flags,
2797 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002798 struct audio_stream_out **stream_out,
2799 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800{
2801 struct audio_device *adev = (struct audio_device *)dev;
2802 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002803 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002804 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302807
2808 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2809 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2810 ALOGE(" sound card is not active rejecting compress output open request");
2811 return -EINVAL;
2812 }
2813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2815
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302816 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2817 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2818 devices, flags, &out->stream);
2819
2820
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002821 if (!out) {
2822 return -ENOMEM;
2823 }
2824
Haynes Mathew George204045b2015-02-25 20:32:03 -08002825 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2826 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 if (devices == AUDIO_DEVICE_NONE)
2829 devices = AUDIO_DEVICE_OUT_SPEAKER;
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out->flags = flags;
2832 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002833 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002834 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 out->sample_rate = config->sample_rate;
2836 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2837 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002838 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002839 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002840 out->non_blocking = 0;
2841 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302843 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2844 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002845 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2846 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2847
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002848 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002849 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2850 ret = read_hdmi_channel_masks(out);
2851
2852 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2853 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002854 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002855 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002856 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002857
2858 if (config->sample_rate == 0)
2859 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2860 if (config->channel_mask == 0)
2861 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2862
2863 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2866 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002868 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002870 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2871 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002872 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002873 ret = voice_extn_compress_voip_open_output_stream(out);
2874 if (ret != 0) {
2875 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2876 __func__, ret);
2877 goto error_open;
2878 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2880 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2881 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2882 ALOGE("%s: Unsupported Offload information", __func__);
2883 ret = -EINVAL;
2884 goto error_open;
2885 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002886
2887 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2888 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2889 ALOGV("read and update_pass through formats");
2890 ret = audio_extn_dolby_update_passt_formats(adev, out);
2891 if(ret != 0) {
2892 goto error_open;
2893 }
2894 if(config->offload_info.format == 0)
2895 config->offload_info.format = out->supported_formats[0];
2896 }
2897
Mingming Yin90310102013-11-13 16:57:00 -08002898 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002899 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 ALOGE("%s: Unsupported audio format", __func__);
2901 ret = -EINVAL;
2902 goto error_open;
2903 }
2904
2905 out->compr_config.codec = (struct snd_codec *)
2906 calloc(1, sizeof(struct snd_codec));
2907
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002908 if (!out->compr_config.codec) {
2909 ret = -ENOMEM;
2910 goto error_open;
2911 }
2912
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002913 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 if (config->offload_info.channel_mask)
2915 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002916 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002918 config->offload_info.channel_mask = config->channel_mask;
2919 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002920 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 out->sample_rate = config->offload_info.sample_rate;
2922
2923 out->stream.set_callback = out_set_callback;
2924 out->stream.pause = out_pause;
2925 out->stream.resume = out_resume;
2926 out->stream.drain = out_drain;
2927 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002928 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002930 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002931 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002932 audio_extn_dolby_get_snd_codec_id(adev, out,
2933 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002934 else
2935 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302937 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002938 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002939 platform_get_pcm_offload_buffer_size(&config->offload_info);
2940 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2941 out->compr_config.fragment_size =
2942 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002943 } else {
2944 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002945 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002946 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2948 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002949 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 out->compr_config.codec->bit_rate =
2951 config->offload_info.bit_rate;
2952 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002953 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302955 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002956 /*TODO: Do we need to change it for passthrough */
2957 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958
Manish Dewangan93672f12015-08-24 20:30:31 +05302959 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2960 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2961 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2962 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002963 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2964 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002965 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002966 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2967
Mingming Yin3ee55c62014-08-04 14:23:35 -07002968 if (out->bit_width == 24) {
2969 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2970 }
2971
Amit Shekhar6f461b12014-08-01 14:52:58 -07002972 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302973 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002975 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2976 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002977
Sharad Sangleb27354b2015-06-18 15:58:55 +05302978 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002979 //this flag is set from framework only if its for PCM formats
2980 //no need to check for PCM format again
2981 out->non_blocking = 0;
2982 out->use_small_bufs = true;
2983 ALOGI("Keep write blocking for small buff: non_blockling %d",
2984 out->non_blocking);
2985 }
2986
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002987 out->send_new_metadata = 1;
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};