blob: 248947150131debc6c2d30e319e1c8d2615de02b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, 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",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
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,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Kuirong Wang993e1f42015-06-28 20:13:24 -0700488 int i, num_devices = 0;
489 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
491
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800492 if (snd_device < SND_DEVICE_MIN ||
493 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800494 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800495 return -EINVAL;
496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700497
498 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700499
500 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
501 ALOGE("%s: Invalid sound device returned", __func__);
502 return -EINVAL;
503 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700504 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700505 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700506 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 return 0;
508 }
509
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530510
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700511 if (audio_extn_spkr_prot_is_enabled())
512 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700513 /* start usb playback thread */
514 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
515 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
516 audio_extn_usb_start_playback(adev);
517
518 /* start usb capture thread */
519 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
520 audio_extn_usb_start_capture(adev);
521
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800522 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
523 audio_extn_spkr_prot_is_enabled()) {
524 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700525 adev->snd_dev_ref_cnt[snd_device]--;
526 return -EINVAL;
527 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200528 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800529 if (audio_extn_spkr_prot_start_processing(snd_device)) {
530 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200531 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800532 return -EINVAL;
533 }
Kuirong Wang993e1f42015-06-28 20:13:24 -0700534 } else if (platform_can_split_snd_device(adev->platform, snd_device,
535 &num_devices, new_snd_devices)) {
536 for (i = 0; i < num_devices; i++) {
537 enable_snd_device(adev, new_snd_devices[i]);
538 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800539 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700540 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700541 /* due to the possibility of calibration overwrite between listen
542 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700547 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700549 audio_extn_sound_trigger_update_device_status(snd_device,
550 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530551 audio_extn_listen_update_device_status(snd_device,
552 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700553 return -EINVAL;
554 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300555 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700556 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530557
558 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
559 !adev->native_playback_enabled &&
560 audio_is_true_native_stream_active(adev)) {
561 ALOGD("%s: %d: napb: enabling native mode in hardware",
562 __func__, __LINE__);
563 audio_route_apply_and_update_path(adev->audio_route,
564 "true-native-mode");
565 adev->native_playback_enabled = true;
566 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800567 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800568 return 0;
569}
570
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700571int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700572 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800573{
Kuirong Wang993e1f42015-06-28 20:13:24 -0700574 int i, num_devices = 0;
575 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700576 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
577
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800578 if (snd_device < SND_DEVICE_MIN ||
579 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800580 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800581 return -EINVAL;
582 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
584 ALOGE("%s: device ref cnt is already 0", __func__);
585 return -EINVAL;
586 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700587
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700589
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700590 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
591 ALOGE("%s: Invalid sound device returned", __func__);
592 return -EINVAL;
593 }
594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700596 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800597 /* exit usb play back thread */
598 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
599 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
600 audio_extn_usb_stop_playback();
601
602 /* exit usb capture thread */
603 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700604 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800605
606 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
607 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700608 audio_extn_spkr_prot_stop_processing(snd_device);
Kuirong Wang993e1f42015-06-28 20:13:24 -0700609 } else if (platform_can_split_snd_device(adev->platform, snd_device,
610 &num_devices, new_snd_devices)) {
611 for (i = 0; i < num_devices; i++) {
612 disable_snd_device(adev, new_snd_devices[i]);
613 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300614 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700615 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300616 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700617
Ashish Jain81eb2a82015-05-13 10:52:34 +0530618 if (snd_device == SND_DEVICE_OUT_HDMI)
619 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530620 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
621 adev->native_playback_enabled) {
622 ALOGD("%s: %d: napb: disabling native mode in hardware",
623 __func__, __LINE__);
624 audio_route_reset_and_update_path(adev->audio_route,
625 "true-native-mode");
626 adev->native_playback_enabled = false;
627 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530628
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200629 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700630 audio_extn_sound_trigger_update_device_status(snd_device,
631 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530632 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800633 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800636 return 0;
637}
638
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639static void check_usecases_codec_backend(struct audio_device *adev,
Kuirong Wang993e1f42015-06-28 20:13:24 -0700640 struct audio_usecase *uc_info,
641 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642{
643 struct listnode *node;
644 struct audio_usecase *usecase;
645 bool switch_device[AUDIO_USECASE_MAX];
646 int i, num_uc_to_switch = 0;
647
648 /*
649 * This function is to make sure that all the usecases that are active on
650 * the hardware codec backend are always routed to any one device that is
651 * handled by the hardware codec.
652 * For example, if low-latency and deep-buffer usecases are currently active
653 * on speaker and out_set_parameters(headset) is received on low-latency
654 * output, then we have to make sure deep-buffer is also switched to headset,
655 * because of the limitation that both the devices cannot be enabled
656 * at the same time as they share the same backend.
657 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700658 /*
659 * This call is to check if we need to force routing for a particular stream
660 * If there is a backend configuration change for the device when a
661 * new stream starts, then ADM needs to be closed and re-opened with the new
662 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800663 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700664 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800665 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
666 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530667
668 ALOGD("%s:becf: force routing %d", __func__, force_routing);
669
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800671 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800672 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 for (i = 0; i < AUDIO_USECASE_MAX; i++)
674 switch_device[i] = false;
675
676 list_for_each(node, &adev->usecase_list) {
677 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800678
Kuirong Wang993e1f42015-06-28 20:13:24 -0700679 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
680 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530681 platform_get_snd_device_name(snd_device),
Kuirong Wang993e1f42015-06-28 20:13:24 -0700682 platform_get_snd_device_name(usecase->out_snd_device),
683 platform_check_backends_match(snd_device, usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800684
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800685 if (usecase->type != PCM_CAPTURE &&
Kuirong Wang993e1f42015-06-28 20:13:24 -0700686 usecase != uc_info &&
687 (usecase->out_snd_device != snd_device || force_routing) &&
688 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
689 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
690 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
691 __func__, use_case_table[usecase->id],
692 platform_get_snd_device_name(usecase->out_snd_device));
693 disable_audio_route(adev, usecase);
694 switch_device[usecase->id] = true;
695 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 }
697 }
698
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530699 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
700 num_uc_to_switch);
701
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700703 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530705 /* Make sure the previous devices to be disabled first and then enable the
706 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 list_for_each(node, &adev->usecase_list) {
708 usecase = node_to_item(node, struct audio_usecase, list);
709 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700710 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 }
712 }
713
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700718 }
719 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 /* Re-route all the usecases on the shared backend other than the
722 specified usecase to new snd devices */
723 list_for_each(node, &adev->usecase_list) {
724 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530725 /* Update the out_snd_device only before enabling the audio route */
726 if (switch_device[usecase->id]) {
727 usecase->out_snd_device = snd_device;
728 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530729 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530730 use_case_table[usecase->id],
731 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530732 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530733 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700734 }
735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 }
737}
738
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739static void check_and_route_capture_usecases(struct audio_device *adev,
740 struct audio_usecase *uc_info,
741 snd_device_t snd_device)
742{
743 struct listnode *node;
744 struct audio_usecase *usecase;
745 bool switch_device[AUDIO_USECASE_MAX];
746 int i, num_uc_to_switch = 0;
747
748 /*
749 * This function is to make sure that all the active capture usecases
750 * are always routed to the same input sound device.
751 * For example, if audio-record and voice-call usecases are currently
752 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
753 * is received for voice call then we have to make sure that audio-record
754 * usecase is also switched to earpiece i.e. voice-dmic-ef,
755 * because of the limitation that two devices cannot be enabled
756 * at the same time if they share the same backend.
757 */
758 for (i = 0; i < AUDIO_USECASE_MAX; i++)
759 switch_device[i] = false;
760
761 list_for_each(node, &adev->usecase_list) {
762 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800763 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700765 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700766 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530767 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
768 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700769 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700770 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
771 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700772 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700773 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 switch_device[usecase->id] = true;
775 num_uc_to_switch++;
776 }
777 }
778
779 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700780 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700781
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530782 /* Make sure the previous devices to be disabled first and then enable the
783 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700784 list_for_each(node, &adev->usecase_list) {
785 usecase = node_to_item(node, struct audio_usecase, list);
786 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700787 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800788 }
789 }
790
791 list_for_each(node, &adev->usecase_list) {
792 usecase = node_to_item(node, struct audio_usecase, list);
793 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700794 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700795 }
796 }
797
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 /* Re-route all the usecases on the shared backend other than the
799 specified usecase to new snd devices */
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
802 /* Update the in_snd_device only before enabling the audio route */
803 if (switch_device[usecase->id] ) {
804 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800805 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530806 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 }
808 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700809 }
810}
811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700813static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700815 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700816 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817
818 switch (channels) {
819 /*
820 * Do not handle stereo output in Multi-channel cases
821 * Stereo case is handled in normal playback path
822 */
823 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700824 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
829 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830 break;
831 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700832 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
833 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
834 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
835 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
836 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
837 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
838 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 break;
840 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700841 ALOGE("HDMI does not support multi channel playback");
842 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843 break;
844 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700845 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846}
847
Alexy Josephb1379942016-01-29 15:49:38 -0800848audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800849 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700850{
851 struct audio_usecase *usecase;
852 struct listnode *node;
853
854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800856 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700857 ALOGV("%s: usecase id %d", __func__, usecase->id);
858 return usecase->id;
859 }
860 }
861 return USECASE_INVALID;
862}
863
Alexy Josephb1379942016-01-29 15:49:38 -0800864struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700865 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700866{
867 struct audio_usecase *usecase;
868 struct listnode *node;
869
870 list_for_each(node, &adev->usecase_list) {
871 usecase = node_to_item(node, struct audio_usecase, list);
872 if (usecase->id == uc_id)
873 return usecase;
874 }
875 return NULL;
876}
877
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530878/*
879 * is a true native playback active
880 */
881bool audio_is_true_native_stream_active(struct audio_device *adev)
882{
883 bool active = false;
884 int i = 0;
885 struct listnode *node;
886
887 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
888 ALOGV("%s:napb: not in true mode or non hdphones device",
889 __func__);
890 active = false;
891 goto exit;
892 }
893
894 list_for_each(node, &adev->usecase_list) {
895 struct audio_usecase *uc;
896 uc = node_to_item(node, struct audio_usecase, list);
897 struct stream_out *curr_out =
898 (struct stream_out*) uc->stream.out;
899
900 if (curr_out && PCM_PLAYBACK == uc->type) {
901 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
902 "(%d) device %s", __func__, i++, use_case_table[uc->id],
903 uc->id, curr_out->sample_rate,
904 curr_out->bit_width,
905 platform_get_snd_device_name(uc->out_snd_device));
906
907 if (is_offload_usecase(uc->id) &&
908 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
909 active = true;
910 ALOGD("%s:napb:native stream detected", __func__);
911 }
912 }
913 }
914exit:
915 return active;
916}
917
918
919static bool force_device_switch(struct audio_usecase *usecase)
920{
921 bool ret = false;
922 bool is_it_true_mode = false;
923
924 if (is_offload_usecase(usecase->id) &&
925 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800926 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
927 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
928 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530929 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
930 if ((is_it_true_mode && !adev->native_playback_enabled) ||
931 (!is_it_true_mode && adev->native_playback_enabled)){
932 ret = true;
933 ALOGD("napb: time to toggle native mode");
934 }
935 }
936
937 return ret;
938}
939
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700940int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800942 snd_device_t out_snd_device = SND_DEVICE_NONE;
943 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 struct audio_usecase *usecase = NULL;
945 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800946 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800947 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800948 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800949 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530952 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 usecase = get_usecase_from_list(adev, uc_id);
955 if (usecase == NULL) {
956 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
957 return -EINVAL;
958 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800960 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800961 (usecase->type == VOIP_CALL) ||
962 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700963 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800964 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700965 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 usecase->devices = usecase->stream.out->devices;
967 } else {
968 /*
969 * If the voice call is active, use the sound devices of voice call usecase
970 * so that it would not result any device switch. All the usecases will
971 * be switched to new device when select_devices() is called for voice call
972 * usecase. This is to avoid switching devices for voice call when
973 * check_usecases_codec_backend() is called below.
974 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800975 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700976 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800977 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700978 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
979 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 in_snd_device = vc_usecase->in_snd_device;
981 out_snd_device = vc_usecase->out_snd_device;
982 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800983 } else if (voice_extn_compress_voip_is_active(adev)) {
984 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700985 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530986 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700987 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800988 in_snd_device = voip_usecase->in_snd_device;
989 out_snd_device = voip_usecase->out_snd_device;
990 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800991 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800992 hfp_ucid = audio_extn_hfp_get_usecase();
993 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700994 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800995 in_snd_device = hfp_usecase->in_snd_device;
996 out_snd_device = hfp_usecase->out_snd_device;
997 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 }
999 if (usecase->type == PCM_PLAYBACK) {
1000 usecase->devices = usecase->stream.out->devices;
1001 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001002 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001003 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001004 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001005 if (usecase->stream.out == adev->primary_output &&
1006 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001007 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001008 select_devices(adev, adev->active_input->usecase);
1009 }
1010 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011 } else if (usecase->type == PCM_CAPTURE) {
1012 usecase->devices = usecase->stream.in->device;
1013 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001014 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001015 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001016 if (adev->active_input &&
1017 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301018 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1019 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1020 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001021 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001022 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001023 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1024 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001025 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001026 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001027 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001028 }
1029 }
1030
1031 if (out_snd_device == usecase->out_snd_device &&
1032 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301033
1034 if (!force_device_switch(usecase))
1035 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 }
1037
sangwoobc677242013-08-08 16:53:43 +09001038 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001039 out_snd_device, platform_get_snd_device_name(out_snd_device),
1040 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 /*
1043 * Limitation: While in call, to do a device switch we need to disable
1044 * and enable both RX and TX devices though one of them is same as current
1045 * device.
1046 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001047 if ((usecase->type == VOICE_CALL) &&
1048 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1049 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001050 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001051 }
1052
1053 if (((usecase->type == VOICE_CALL) ||
1054 (usecase->type == VOIP_CALL)) &&
1055 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1056 /* Disable sidetone only if voice/voip call already exists */
1057 if (voice_is_call_state_active(adev) ||
1058 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001059 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001060 }
1061
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 /* Disable current sound devices */
1063 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001064 disable_audio_route(adev, usecase);
1065 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 }
1067
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001069 disable_audio_route(adev, usecase);
1070 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 }
1072
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001073 /* Applicable only on the targets that has external modem.
1074 * New device information should be sent to modem before enabling
1075 * the devices to reduce in-call device switch time.
1076 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001077 if ((usecase->type == VOICE_CALL) &&
1078 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1079 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001080 status = platform_switch_voice_call_enable_device_config(adev->platform,
1081 out_snd_device,
1082 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001083 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001084
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 /* Enable new sound devices */
1086 if (out_snd_device != SND_DEVICE_NONE) {
1087 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1088 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001089 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 }
1091
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001092 if (in_snd_device != SND_DEVICE_NONE) {
1093 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001094 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001095 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096
Avinash Vaish71a8b972014-07-24 15:36:33 +05301097 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001098 status = platform_switch_voice_call_device_post(adev->platform,
1099 out_snd_device,
1100 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301101 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001102 /* Enable sidetone only if voice/voip call already exists */
1103 if (voice_is_call_state_active(adev) ||
1104 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001105 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301106 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001107
sangwoo170731f2013-06-08 15:36:36 +09001108 usecase->in_snd_device = in_snd_device;
1109 usecase->out_snd_device = out_snd_device;
1110
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301111 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001112 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301113 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001114 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301115 usecase->stream.out->flags,
1116 usecase->stream.out->format,
1117 usecase->stream.out->sample_rate,
1118 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301119 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301120 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001121 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301122 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001123
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001124 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001125
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001126 /* Applicable only on the targets that has external modem.
1127 * Enable device command should be sent to modem only after
1128 * enabling voice call mixer controls
1129 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001130 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001131 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1132 out_snd_device,
1133 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301134 ALOGD("%s: done",__func__);
1135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 return status;
1137}
1138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139static int stop_input_stream(struct stream_in *in)
1140{
1141 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 struct audio_usecase *uc_info;
1143 struct audio_device *adev = in->dev;
1144
Eric Laurentc8400632013-02-14 19:04:54 -08001145 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146
Eric Laurent994a6932013-07-17 11:51:42 -07001147 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 uc_info = get_usecase_from_list(adev, in->usecase);
1150 if (uc_info == NULL) {
1151 ALOGE("%s: Could not find the usecase (%d) in the list",
1152 __func__, in->usecase);
1153 return -EINVAL;
1154 }
1155
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001156 /* Close in-call recording streams */
1157 voice_check_and_stop_incall_rec_usecase(adev, in);
1158
Eric Laurent150dbfe2013-02-27 14:31:02 -08001159 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001160 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161
1162 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001163 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001165 list_remove(&uc_info->list);
1166 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167
Eric Laurent994a6932013-07-17 11:51:42 -07001168 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169 return ret;
1170}
1171
1172int start_input_stream(struct stream_in *in)
1173{
1174 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001175 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 struct audio_usecase *uc_info;
1177 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301178 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Mingming Yin2664a5b2015-09-03 10:53:11 -07001180 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1181 if (get_usecase_from_list(adev, usecase) == NULL)
1182 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301183 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1184 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001185
Naresh Tanniru80659832014-06-04 18:17:56 +05301186
1187 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301188 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301189 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301190 goto error_config;
1191 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301192
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001193 /* Check if source matches incall recording usecase criteria */
1194 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1195 if (ret)
1196 goto error_config;
1197 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001198 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1199
1200 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1201 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1202 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1203 goto error_config;
1204 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001205
Eric Laurentb23d5282013-05-14 15:27:20 -07001206 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207 if (in->pcm_device_id < 0) {
1208 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1209 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001210 ret = -EINVAL;
1211 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001213
1214 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001216
1217 if (!uc_info) {
1218 ret = -ENOMEM;
1219 goto error_config;
1220 }
1221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 uc_info->id = in->usecase;
1223 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001224 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225 uc_info->devices = in->device;
1226 uc_info->in_snd_device = SND_DEVICE_NONE;
1227 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001229 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301230 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1231 adev->perf_lock_opts,
1232 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001233 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234
Eric Laurentc8400632013-02-14 19:04:54 -08001235 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001236 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1237
1238 unsigned int flags = PCM_IN;
1239 unsigned int pcm_open_retry_count = 0;
1240
1241 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1242 flags |= PCM_MMAP | PCM_NOIRQ;
1243 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1244 }
1245
1246 while (1) {
1247 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1248 flags, &in->config);
1249 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1250 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1251 if (in->pcm != NULL) {
1252 pcm_close(in->pcm);
1253 in->pcm = NULL;
1254 }
1255 if (pcm_open_retry_count-- == 0) {
1256 ret = -EIO;
1257 goto error_open;
1258 }
1259 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1260 continue;
1261 }
1262 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001264
1265 ALOGV("%s: pcm_prepare", __func__);
1266 ret = pcm_prepare(in->pcm);
1267 if (ret < 0) {
1268 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1269 pcm_close(in->pcm);
1270 in->pcm = NULL;
1271 goto error_open;
1272 }
1273
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301274 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001275 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001276
Eric Laurentc8400632013-02-14 19:04:54 -08001277 return ret;
1278
1279error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301280 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001282error_config:
1283 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301284 /*
1285 * sleep 50ms to allow sufficient time for kernel
1286 * drivers to recover incases like SSR.
1287 */
1288 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001290
1291 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292}
1293
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001294void lock_input_stream(struct stream_in *in)
1295{
1296 pthread_mutex_lock(&in->pre_lock);
1297 pthread_mutex_lock(&in->lock);
1298 pthread_mutex_unlock(&in->pre_lock);
1299}
1300
1301void lock_output_stream(struct stream_out *out)
1302{
1303 pthread_mutex_lock(&out->pre_lock);
1304 pthread_mutex_lock(&out->lock);
1305 pthread_mutex_unlock(&out->pre_lock);
1306}
1307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001308/* must be called with out->lock locked */
1309static int send_offload_cmd_l(struct stream_out* out, int command)
1310{
1311 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1312
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001313 if (!cmd) {
1314 ALOGE("failed to allocate mem for command 0x%x", command);
1315 return -ENOMEM;
1316 }
1317
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 ALOGVV("%s %d", __func__, command);
1319
1320 cmd->cmd = command;
1321 list_add_tail(&out->offload_cmd_list, &cmd->node);
1322 pthread_cond_signal(&out->offload_cond);
1323 return 0;
1324}
1325
1326/* must be called iwth out->lock locked */
1327static void stop_compressed_output_l(struct stream_out *out)
1328{
1329 out->offload_state = OFFLOAD_STATE_IDLE;
1330 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001331 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 if (out->compr != NULL) {
1333 compress_stop(out->compr);
1334 while (out->offload_thread_blocked) {
1335 pthread_cond_wait(&out->cond, &out->lock);
1336 }
1337 }
1338}
1339
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001340bool is_offload_usecase(audio_usecase_t uc_id)
1341{
1342 unsigned int i;
1343 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1344 if (uc_id == offload_usecases[i])
1345 return true;
1346 }
1347 return false;
1348}
1349
vivek mehta446c3962015-09-14 10:57:35 -07001350static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001351{
vivek mehta446c3962015-09-14 10:57:35 -07001352 audio_usecase_t ret_uc = USECASE_INVALID;
1353 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001354 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001355 if (!adev->multi_offload_enable) {
1356 if (is_direct_pcm)
1357 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1358 else
1359 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001360
vivek mehta446c3962015-09-14 10:57:35 -07001361 pthread_mutex_lock(&adev->lock);
1362 if (get_usecase_from_list(adev, ret_uc) != NULL)
1363 ret_uc = USECASE_INVALID;
1364 pthread_mutex_unlock(&adev->lock);
1365
1366 return ret_uc;
1367 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001368
1369 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001370 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1371 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1372 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1373 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001374 break;
1375 }
1376 }
vivek mehta446c3962015-09-14 10:57:35 -07001377
1378 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1379 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001380}
1381
1382static void free_offload_usecase(struct audio_device *adev,
1383 audio_usecase_t uc_id)
1384{
vivek mehta446c3962015-09-14 10:57:35 -07001385 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001386 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001387
1388 if (!adev->multi_offload_enable)
1389 return;
1390
1391 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1392 if (offload_usecases[offload_uc_index] == uc_id) {
1393 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001394 break;
1395 }
1396 }
1397 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1398}
1399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400static void *offload_thread_loop(void *context)
1401{
1402 struct stream_out *out = (struct stream_out *) context;
1403 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001404 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001405
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001406 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1407 set_sched_policy(0, SP_FOREGROUND);
1408 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1409
1410 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001411 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001412 for (;;) {
1413 struct offload_cmd *cmd = NULL;
1414 stream_callback_event_t event;
1415 bool send_callback = false;
1416
1417 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1418 __func__, list_empty(&out->offload_cmd_list),
1419 out->offload_state);
1420 if (list_empty(&out->offload_cmd_list)) {
1421 ALOGV("%s SLEEPING", __func__);
1422 pthread_cond_wait(&out->offload_cond, &out->lock);
1423 ALOGV("%s RUNNING", __func__);
1424 continue;
1425 }
1426
1427 item = list_head(&out->offload_cmd_list);
1428 cmd = node_to_item(item, struct offload_cmd, node);
1429 list_remove(item);
1430
1431 ALOGVV("%s STATE %d CMD %d out->compr %p",
1432 __func__, out->offload_state, cmd->cmd, out->compr);
1433
1434 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1435 free(cmd);
1436 break;
1437 }
1438
1439 if (out->compr == NULL) {
1440 ALOGE("%s: Compress handle is NULL", __func__);
1441 pthread_cond_signal(&out->cond);
1442 continue;
1443 }
1444 out->offload_thread_blocked = true;
1445 pthread_mutex_unlock(&out->lock);
1446 send_callback = false;
1447 switch(cmd->cmd) {
1448 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001449 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001450 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001451 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001452 send_callback = true;
1453 event = STREAM_CBK_EVENT_WRITE_READY;
1454 break;
1455 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001456 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301457 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001458 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301459 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001460 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301461 if (ret < 0)
1462 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301463 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301464 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001465 compress_drain(out->compr);
1466 else
1467 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301468 if (ret != -ENETRESET) {
1469 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301470 pthread_mutex_lock(&out->lock);
1471 out->send_new_metadata = 1;
1472 out->send_next_track_params = true;
1473 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301474 event = STREAM_CBK_EVENT_DRAIN_READY;
1475 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1476 } else
1477 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478 break;
1479 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001480 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001482 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483 send_callback = true;
1484 event = STREAM_CBK_EVENT_DRAIN_READY;
1485 break;
1486 default:
1487 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1488 break;
1489 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001490 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001491 out->offload_thread_blocked = false;
1492 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001493 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001494 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001495 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001496 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001497 free(cmd);
1498 }
1499
1500 pthread_cond_signal(&out->cond);
1501 while (!list_empty(&out->offload_cmd_list)) {
1502 item = list_head(&out->offload_cmd_list);
1503 list_remove(item);
1504 free(node_to_item(item, struct offload_cmd, node));
1505 }
1506 pthread_mutex_unlock(&out->lock);
1507
1508 return NULL;
1509}
1510
1511static int create_offload_callback_thread(struct stream_out *out)
1512{
1513 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1514 list_init(&out->offload_cmd_list);
1515 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1516 offload_thread_loop, out);
1517 return 0;
1518}
1519
1520static int destroy_offload_callback_thread(struct stream_out *out)
1521{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001522 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001523 stop_compressed_output_l(out);
1524 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1525
1526 pthread_mutex_unlock(&out->lock);
1527 pthread_join(out->offload_thread, (void **) NULL);
1528 pthread_cond_destroy(&out->offload_cond);
1529
1530 return 0;
1531}
1532
Eric Laurent07eeafd2013-10-06 12:52:49 -07001533static bool allow_hdmi_channel_config(struct audio_device *adev)
1534{
1535 struct listnode *node;
1536 struct audio_usecase *usecase;
1537 bool ret = true;
1538
1539 list_for_each(node, &adev->usecase_list) {
1540 usecase = node_to_item(node, struct audio_usecase, list);
1541 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1542 /*
1543 * If voice call is already existing, do not proceed further to avoid
1544 * disabling/enabling both RX and TX devices, CSD calls, etc.
1545 * Once the voice call done, the HDMI channels can be configured to
1546 * max channels of remaining use cases.
1547 */
1548 if (usecase->id == USECASE_VOICE_CALL) {
1549 ALOGD("%s: voice call is active, no change in HDMI channels",
1550 __func__);
1551 ret = false;
1552 break;
1553 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1554 ALOGD("%s: multi channel playback is active, "
1555 "no change in HDMI channels", __func__);
1556 ret = false;
1557 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001558 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001559 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1561 ", no change in HDMI channels", __func__,
1562 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001563 ret = false;
1564 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 }
1566 }
1567 }
1568 return ret;
1569}
1570
1571static int check_and_set_hdmi_channels(struct audio_device *adev,
1572 unsigned int channels)
1573{
1574 struct listnode *node;
1575 struct audio_usecase *usecase;
1576
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001577 unsigned int supported_channels = platform_edid_get_max_channels(
1578 adev->platform);
1579 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 /* Check if change in HDMI channel config is allowed */
1581 if (!allow_hdmi_channel_config(adev))
1582 return 0;
1583
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 if (channels > supported_channels)
1585 channels = supported_channels;
1586
Eric Laurent07eeafd2013-10-06 12:52:49 -07001587 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001588 ALOGD("%s: Requested channels are same as current channels(%d)",
1589 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001590 return 0;
1591 }
1592
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001593 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001594 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001595 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001596 adev->cur_hdmi_channels = channels;
1597
1598 /*
1599 * Deroute all the playback streams routed to HDMI so that
1600 * the back end is deactivated. Note that backend will not
1601 * be deactivated if any one stream is connected to it.
1602 */
1603 list_for_each(node, &adev->usecase_list) {
1604 usecase = node_to_item(node, struct audio_usecase, list);
1605 if (usecase->type == PCM_PLAYBACK &&
1606 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001607 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001608 }
1609 }
1610
1611 /*
1612 * Enable all the streams disabled above. Now the HDMI backend
1613 * will be activated with new channel configuration
1614 */
1615 list_for_each(node, &adev->usecase_list) {
1616 usecase = node_to_item(node, struct audio_usecase, list);
1617 if (usecase->type == PCM_PLAYBACK &&
1618 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001619 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001620 }
1621 }
1622
1623 return 0;
1624}
1625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626static int stop_output_stream(struct stream_out *out)
1627{
1628 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 struct audio_usecase *uc_info;
1630 struct audio_device *adev = out->dev;
1631
Eric Laurent994a6932013-07-17 11:51:42 -07001632 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001633 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 uc_info = get_usecase_from_list(adev, out->usecase);
1635 if (uc_info == NULL) {
1636 ALOGE("%s: Could not find the usecase (%d) in the list",
1637 __func__, out->usecase);
1638 return -EINVAL;
1639 }
1640
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001641 if (is_offload_usecase(out->usecase) &&
1642 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001643 if (adev->visualizer_stop_output != NULL)
1644 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001645
1646 audio_extn_dts_remove_state_notifier_node(out->usecase);
1647
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001648 if (adev->offload_effects_stop_output != NULL)
1649 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1650 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001651
Eric Laurent150dbfe2013-02-27 14:31:02 -08001652 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001653 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001654
1655 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001656 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001658 list_remove(&uc_info->list);
1659 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001661 if (is_offload_usecase(out->usecase) &&
1662 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1663 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1664 ALOGV("Disable passthrough , reset mixer to pcm");
1665 /* NO_PASSTHROUGH */
1666 out->compr_config.codec->compr_passthr = 0;
1667 audio_extn_dolby_set_hdmi_config(adev, out);
1668 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1669 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001670 /* Must be called after removing the usecase from list */
1671 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1672 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1673
Eric Laurent994a6932013-07-17 11:51:42 -07001674 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 return ret;
1676}
1677
1678int start_output_stream(struct stream_out *out)
1679{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001681 int sink_channels = 0;
1682 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 struct audio_usecase *uc_info;
1684 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301685 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001687 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1688 ret = -EINVAL;
1689 goto error_config;
1690 }
1691
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301692 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1693 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1694 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301695
Naresh Tanniru80659832014-06-04 18:17:56 +05301696 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301697 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301698 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301699 goto error_config;
1700 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301701
Eric Laurentb23d5282013-05-14 15:27:20 -07001702 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 if (out->pcm_device_id < 0) {
1704 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1705 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001706 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001707 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 }
1709
1710 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001711
1712 if (!uc_info) {
1713 ret = -ENOMEM;
1714 goto error_config;
1715 }
1716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 uc_info->id = out->usecase;
1718 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001719 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001720 uc_info->devices = out->devices;
1721 uc_info->in_snd_device = SND_DEVICE_NONE;
1722 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001723 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001724 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001725 if (is_offload_usecase(out->usecase)) {
1726 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001727 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1728 }
1729 }
Mingming Yin9c041392014-05-01 15:37:31 -07001730 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1731 if (!strncmp("true", prop_value, 4)) {
1732 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001733 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1734 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001735 check_and_set_hdmi_channels(adev, sink_channels);
1736 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001737 if (is_offload_usecase(out->usecase)) {
1738 unsigned int ch_count = out->compr_config.codec->ch_in;
1739 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1740 /* backend channel config for passthrough stream is stereo */
1741 ch_count = 2;
1742 check_and_set_hdmi_channels(adev, ch_count);
1743 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001744 check_and_set_hdmi_channels(adev, out->config.channels);
1745 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001746 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001747 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001748 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301750 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1751 adev->perf_lock_opts,
1752 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 select_devices(adev, out->usecase);
1754
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001755 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1756 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001757 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001758 unsigned int flags = PCM_OUT;
1759 unsigned int pcm_open_retry_count = 0;
1760 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1761 flags |= PCM_MMAP | PCM_NOIRQ;
1762 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1763 } else
1764 flags |= PCM_MONOTONIC;
1765
1766 while (1) {
1767 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1768 flags, &out->config);
1769 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1770 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1771 if (out->pcm != NULL) {
1772 pcm_close(out->pcm);
1773 out->pcm = NULL;
1774 }
1775 if (pcm_open_retry_count-- == 0) {
1776 ret = -EIO;
1777 goto error_open;
1778 }
1779 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1780 continue;
1781 }
1782 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001784
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001785 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1786 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001787
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001788 ALOGV("%s: pcm_prepare", __func__);
1789 if (pcm_is_ready(out->pcm)) {
1790 ret = pcm_prepare(out->pcm);
1791 if (ret < 0) {
1792 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1793 pcm_close(out->pcm);
1794 out->pcm = NULL;
1795 goto error_open;
1796 }
1797 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001799 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1800 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001802 out->compr = compress_open(adev->snd_card,
1803 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 COMPRESS_IN, &out->compr_config);
1805 if (out->compr && !is_compress_ready(out->compr)) {
1806 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1807 compress_close(out->compr);
1808 out->compr = NULL;
1809 ret = -EIO;
1810 goto error_open;
1811 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301812 /* compress_open sends params of the track, so reset the flag here */
1813 out->is_compr_metadata_avail = false;
1814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001815 if (out->offload_callback)
1816 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001817
Fred Oh3f43e742015-03-04 18:42:34 -08001818 /* Since small bufs uses blocking writes, a write will be blocked
1819 for the default max poll time (20s) in the event of an SSR.
1820 Reduce the poll time to observe and deal with SSR faster.
1821 */
1822 if (out->use_small_bufs) {
1823 compress_set_max_poll_wait(out->compr, 1000);
1824 }
1825
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001826 audio_extn_dts_create_state_notifier_node(out->usecase);
1827 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1828 popcount(out->channel_mask),
1829 out->playback_started);
1830
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001831#ifdef DS1_DOLBY_DDP_ENABLED
1832 if (audio_extn_is_dolby_format(out->format))
1833 audio_extn_dolby_send_ddp_endp_params(adev);
1834#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001835 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1836 if (adev->visualizer_start_output != NULL)
1837 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1838 if (adev->offload_effects_start_output != NULL)
1839 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001840 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301843 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001844 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301848 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001850error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301851 /*
1852 * sleep 50ms to allow sufficient time for kernel
1853 * drivers to recover incases like SSR.
1854 */
1855 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001856 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857}
1858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859static int check_input_parameters(uint32_t sample_rate,
1860 audio_format_t format,
1861 int channel_count)
1862{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001863 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001865 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001866 !voice_extn_compress_voip_is_format_supported(format) &&
1867 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001868
1869 switch (channel_count) {
1870 case 1:
1871 case 2:
1872 case 6:
1873 break;
1874 default:
1875 ret = -EINVAL;
1876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877
1878 switch (sample_rate) {
1879 case 8000:
1880 case 11025:
1881 case 12000:
1882 case 16000:
1883 case 22050:
1884 case 24000:
1885 case 32000:
1886 case 44100:
1887 case 48000:
1888 break;
1889 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001890 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 }
1892
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001893 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894}
1895
1896static size_t get_input_buffer_size(uint32_t sample_rate,
1897 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001898 int channel_count,
1899 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900{
1901 size_t size = 0;
1902
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001903 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1904 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001906 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001907 if (is_low_latency)
1908 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001909 /* ToDo: should use frame_size computed based on the format and
1910 channel_count here. */
1911 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001913 /* make sure the size is multiple of 32 bytes
1914 * At 48 kHz mono 16-bit PCM:
1915 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1916 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1917 */
1918 size += 0x1f;
1919 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001920
1921 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922}
1923
1924static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1925{
1926 struct stream_out *out = (struct stream_out *)stream;
1927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001928 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929}
1930
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001931static int out_set_sample_rate(struct audio_stream *stream __unused,
1932 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933{
1934 return -ENOSYS;
1935}
1936
1937static size_t out_get_buffer_size(const struct audio_stream *stream)
1938{
1939 struct stream_out *out = (struct stream_out *)stream;
1940
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001941 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001943 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1944 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001946 return out->config.period_size *
1947 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948}
1949
1950static uint32_t out_get_channels(const struct audio_stream *stream)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953
1954 return out->channel_mask;
1955}
1956
1957static audio_format_t out_get_format(const struct audio_stream *stream)
1958{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 struct stream_out *out = (struct stream_out *)stream;
1960
1961 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962}
1963
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001964static int out_set_format(struct audio_stream *stream __unused,
1965 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966{
1967 return -ENOSYS;
1968}
1969
1970static int out_standby(struct audio_stream *stream)
1971{
1972 struct stream_out *out = (struct stream_out *)stream;
1973 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301975 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1976 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001977 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1978 /* Ignore standby in case of voip call because the voip output
1979 * stream is closed in adev_close_output_stream()
1980 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301981 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001982 return 0;
1983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001985 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001987 if (adev->adm_deregister_stream)
1988 adev->adm_deregister_stream(adev->adm_data, out->handle);
1989
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001990 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001992 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 if (out->pcm) {
1994 pcm_close(out->pcm);
1995 out->pcm = NULL;
1996 }
1997 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001998 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001999 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302000 out->send_next_track_params = false;
2001 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002002 out->gapless_mdata.encoder_delay = 0;
2003 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 if (out->compr != NULL) {
2005 compress_close(out->compr);
2006 out->compr = NULL;
2007 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002010 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 }
2012 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302013 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 return 0;
2015}
2016
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002017static int out_dump(const struct audio_stream *stream __unused,
2018 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019{
2020 return 0;
2021}
2022
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002023static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2024{
2025 int ret = 0;
2026 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002027
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002028 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002029 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 return -EINVAL;
2031 }
2032
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302033 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002034
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002035 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2036 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302037 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002038 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2040 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302041 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002042 }
2043
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002044 ALOGV("%s new encoder delay %u and padding %u", __func__,
2045 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2046
2047 return 0;
2048}
2049
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002050static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2051{
2052 return out == adev->primary_output || out == adev->voice_tx_output;
2053}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2056{
2057 struct stream_out *out = (struct stream_out *)stream;
2058 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002059 struct audio_usecase *usecase;
2060 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 struct str_parms *parms;
2062 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002063 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002064 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
sangwoobc677242013-08-08 16:53:43 +09002066 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002067 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302069 if (!parms)
2070 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002071 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2072 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002074 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002075 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302078 * When HDMI cable is unplugged/usb hs is disconnected the
2079 * music playback is paused and the policy manager sends routing=0
2080 * But the audioflingercontinues to write data until standby time
2081 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002082 * Avoid this by routing audio to speaker until standby.
2083 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302084 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2085 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002086 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002087 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2088 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002089 }
2090
2091 /*
2092 * select_devices() call below switches all the usecases on the same
2093 * backend to the new device. Refer to check_usecases_codec_backend() in
2094 * the select_devices(). But how do we undo this?
2095 *
2096 * For example, music playback is active on headset (deep-buffer usecase)
2097 * and if we go to ringtones and select a ringtone, low-latency usecase
2098 * will be started on headset+speaker. As we can't enable headset+speaker
2099 * and headset devices at the same time, select_devices() switches the music
2100 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2101 * So when the ringtone playback is completed, how do we undo the same?
2102 *
2103 * We are relying on the out_set_parameters() call on deep-buffer output,
2104 * once the ringtone playback is ended.
2105 * NOTE: We should not check if the current devices are same as new devices.
2106 * Because select_devices() must be called to switch back the music
2107 * playback to headset.
2108 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002109 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002110 out->devices = val;
2111
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302112 if (!out->standby) {
2113 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2114 adev->perf_lock_opts,
2115 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002116 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302117 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2118 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002119
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002120 if (output_drives_call(adev, out)) {
2121 if(!voice_is_in_call(adev)) {
2122 if (adev->mode == AUDIO_MODE_IN_CALL) {
2123 adev->current_call_output = out;
2124 ret = voice_start_call(adev);
2125 }
2126 } else {
2127 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002128 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002129 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002130 }
2131 }
2132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002136
2137 if (out == adev->primary_output) {
2138 pthread_mutex_lock(&adev->lock);
2139 audio_extn_set_parameters(adev, parms);
2140 pthread_mutex_unlock(&adev->lock);
2141 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002142 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002143 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002144 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002145
2146 audio_extn_dts_create_state_notifier_node(out->usecase);
2147 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2148 popcount(out->channel_mask),
2149 out->playback_started);
2150
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002151 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302155error:
Eric Laurent994a6932013-07-17 11:51:42 -07002156 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 return ret;
2158}
2159
2160static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2161{
2162 struct stream_out *out = (struct stream_out *)stream;
2163 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002164 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 char value[256];
2166 struct str_parms *reply = str_parms_create();
2167 size_t i, j;
2168 int ret;
2169 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002170
2171 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002172 if (reply) {
2173 str_parms_destroy(reply);
2174 }
2175 if (query) {
2176 str_parms_destroy(query);
2177 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002178 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2179 return NULL;
2180 }
2181
Eric Laurent994a6932013-07-17 11:51:42 -07002182 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2184 if (ret >= 0) {
2185 value[0] = '\0';
2186 i = 0;
2187 while (out->supported_channel_masks[i] != 0) {
2188 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2189 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2190 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002191 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002193 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 first = false;
2195 break;
2196 }
2197 }
2198 i++;
2199 }
2200 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2201 str = str_parms_to_str(reply);
2202 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002203 voice_extn_out_get_parameters(out, query, reply);
2204 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002205 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002206 free(str);
2207 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002210
Alexy Joseph62142aa2015-11-16 15:10:34 -08002211
2212 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2213 if (ret >= 0) {
2214 value[0] = '\0';
2215 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2216 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302217 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002218 } else {
2219 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302220 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002221 }
2222 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002223 if (str)
2224 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002225 str = str_parms_to_str(reply);
2226 }
2227
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002228 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2229 if (ret >= 0) {
2230 value[0] = '\0';
2231 i = 0;
2232 first = true;
2233 while (out->supported_formats[i] != 0) {
2234 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2235 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2236 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002237 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002238 }
2239 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2240 first = false;
2241 break;
2242 }
2243 }
2244 i++;
2245 }
2246 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002247 if (str)
2248 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002249 str = str_parms_to_str(reply);
2250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 str_parms_destroy(query);
2252 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002253 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 return str;
2255}
2256
2257static uint32_t out_get_latency(const struct audio_stream_out *stream)
2258{
2259 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002260 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261
Alexy Josephaa54c872014-12-03 02:46:47 -08002262 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002263 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002264 } else {
2265 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002267 }
2268
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302269 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002270 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271}
2272
2273static int out_set_volume(struct audio_stream_out *stream, float left,
2274 float right)
2275{
Eric Laurenta9024de2013-04-04 09:19:12 -07002276 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 int volume[2];
2278
Eric Laurenta9024de2013-04-04 09:19:12 -07002279 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2280 /* only take left channel into account: the API is for stereo anyway */
2281 out->muted = (left == 0.0f);
2282 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002283 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002284 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2285 /*
2286 * Set mute or umute on HDMI passthrough stream.
2287 * Only take left channel into account.
2288 * Mute is 0 and unmute 1
2289 */
2290 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2291 } else {
2292 char mixer_ctl_name[128];
2293 struct audio_device *adev = out->dev;
2294 struct mixer_ctl *ctl;
2295 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002296 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002297
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002298 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2299 "Compress Playback %d Volume", pcm_device_id);
2300 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2301 if (!ctl) {
2302 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2303 __func__, mixer_ctl_name);
2304 return -EINVAL;
2305 }
2306 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2307 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2308 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2309 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002311 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 return -ENOSYS;
2314}
2315
2316static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2317 size_t bytes)
2318{
2319 struct stream_out *out = (struct stream_out *)stream;
2320 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302321 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002322 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002324 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302325
Naresh Tanniru80659832014-06-04 18:17:56 +05302326 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002327
Ashish Jainbbce4322016-02-16 13:25:27 +05302328 if (is_offload_usecase(out->usecase)) {
2329 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302330 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2331 pthread_mutex_unlock(&out->lock);
2332 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302333 } else {
2334 /* increase written size during SSR to avoid mismatch
2335 * with the written frames count in AF
2336 */
2337 out->written += bytes / (out->config.channels * sizeof(short));
2338 ALOGD(" %s: sound card is not active/SSR state", __func__);
2339 ret= -EIO;
2340 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302341 }
2342 }
2343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002345 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002346 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002347 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2348 ret = voice_extn_compress_voip_start_output_stream(out);
2349 else
2350 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002351 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002354 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 goto exit;
2356 }
vivek mehta446c3962015-09-14 10:57:35 -07002357 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002358 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360
Ashish Jain81eb2a82015-05-13 10:52:34 +05302361 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002362 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302363 adev->is_channel_status_set = true;
2364 }
2365
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002366 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002367 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002368 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002369 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2371 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302372 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2373 ALOGD("copl(%p):send next track params in gapless", out);
2374 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2375 out->send_next_track_params = false;
2376 out->is_compr_metadata_avail = false;
2377 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002378 }
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302381 if (ret < 0)
2382 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002383 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002384 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302385 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302387 } else if (-ENETRESET == ret) {
2388 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2389 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2390 pthread_mutex_unlock(&out->lock);
2391 out_standby(&out->stream.common);
2392 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302394 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002396 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 out->playback_started = 1;
2398 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399
2400 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2401 popcount(out->channel_mask),
2402 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 }
2404 pthread_mutex_unlock(&out->lock);
2405 return ret;
2406 } else {
2407 if (out->pcm) {
2408 if (out->muted)
2409 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002411 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002412
2413 if (adev->adm_request_focus)
2414 adev->adm_request_focus(adev->adm_data, out->handle);
2415
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002416 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2417 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2418 else
2419 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002420
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302421 if (ret < 0)
2422 ret = -errno;
2423 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002424 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002425
2426 if (adev->adm_abandon_focus)
2427 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429 }
2430
2431exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302432 /* ToDo: There may be a corner case when SSR happens back to back during
2433 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302434 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302435 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302436 }
2437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 pthread_mutex_unlock(&out->lock);
2439
2440 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002441 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002442 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302443 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302444 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302445 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302446 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302447 out->standby = true;
2448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302450 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302451 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 }
2453 return bytes;
2454}
2455
2456static int out_get_render_position(const struct audio_stream_out *stream,
2457 uint32_t *dsp_frames)
2458{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302460 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002461
2462 if (dsp_frames == NULL)
2463 return -EINVAL;
2464
2465 *dsp_frames = 0;
2466 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002467 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002468 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302470 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302472 if (ret < 0)
2473 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 ALOGVV("%s rendered frames %d sample_rate %d",
2475 __func__, *dsp_frames, out->sample_rate);
2476 }
2477 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302478 if (-ENETRESET == ret) {
2479 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2480 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2481 return -EINVAL;
2482 } else if(ret < 0) {
2483 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2484 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302485 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2486 /*
2487 * Handle corner case where compress session is closed during SSR
2488 * and timestamp is queried
2489 */
2490 ALOGE(" ERROR: sound card not active, return error");
2491 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302492 } else {
2493 return 0;
2494 }
Zhou Song32a556e2015-05-05 10:46:56 +08002495 } else if (audio_is_linear_pcm(out->format)) {
2496 *dsp_frames = out->written;
2497 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 } else
2499 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500}
2501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002502static int out_add_audio_effect(const struct audio_stream *stream __unused,
2503 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504{
2505 return 0;
2506}
2507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002508static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2509 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510{
2511 return 0;
2512}
2513
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002514static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2515 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516{
2517 return -EINVAL;
2518}
2519
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002520static int out_get_presentation_position(const struct audio_stream_out *stream,
2521 uint64_t *frames, struct timespec *timestamp)
2522{
2523 struct stream_out *out = (struct stream_out *)stream;
2524 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002525 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002526
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002527 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002528
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002529 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002530 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302531 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002532 &out->sample_rate);
2533 ALOGVV("%s rendered frames %ld sample_rate %d",
2534 __func__, dsp_frames, out->sample_rate);
2535 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302536 if (ret < 0)
2537 ret = -errno;
2538 if (-ENETRESET == ret) {
2539 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2540 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2541 ret = -EINVAL;
2542 } else
2543 ret = 0;
2544
Eric Laurent949a0892013-09-20 09:20:13 -07002545 /* this is the best we can do */
2546 clock_gettime(CLOCK_MONOTONIC, timestamp);
2547 }
2548 } else {
2549 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002550 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002551 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2552 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002553 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002554 // This adjustment accounts for buffering after app processor.
2555 // It is based on estimated DSP latency per use case, rather than exact.
2556 signed_frames -=
2557 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2558
Eric Laurent949a0892013-09-20 09:20:13 -07002559 // It would be unusual for this value to be negative, but check just in case ...
2560 if (signed_frames >= 0) {
2561 *frames = signed_frames;
2562 ret = 0;
2563 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002564 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302565 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2566 *frames = out->written;
2567 clock_gettime(CLOCK_MONOTONIC, timestamp);
2568 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002569 }
2570 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002571 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002572 return ret;
2573}
2574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575static int out_set_callback(struct audio_stream_out *stream,
2576 stream_callback_t callback, void *cookie)
2577{
2578 struct stream_out *out = (struct stream_out *)stream;
2579
2580 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002581 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 out->offload_callback = callback;
2583 out->offload_cookie = cookie;
2584 pthread_mutex_unlock(&out->lock);
2585 return 0;
2586}
2587
2588static int out_pause(struct audio_stream_out* stream)
2589{
2590 struct stream_out *out = (struct stream_out *)stream;
2591 int status = -ENOSYS;
2592 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002593 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002594 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002595 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302597 struct audio_device *adev = out->dev;
2598 int snd_scard_state = get_snd_card_state(adev);
2599
2600 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2601 status = compress_pause(out->compr);
2602
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002604
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302605 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002606 audio_extn_dts_notify_playback_state(out->usecase, 0,
2607 out->sample_rate, popcount(out->channel_mask),
2608 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609 }
2610 pthread_mutex_unlock(&out->lock);
2611 }
2612 return status;
2613}
2614
2615static int out_resume(struct audio_stream_out* stream)
2616{
2617 struct stream_out *out = (struct stream_out *)stream;
2618 int status = -ENOSYS;
2619 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002620 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002621 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002623 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302625 struct audio_device *adev = out->dev;
2626 int snd_scard_state = get_snd_card_state(adev);
2627
2628 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2629 status = compress_resume(out->compr);
2630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002631 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002632
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302633 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002634 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2635 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002636 }
2637 pthread_mutex_unlock(&out->lock);
2638 }
2639 return status;
2640}
2641
2642static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2643{
2644 struct stream_out *out = (struct stream_out *)stream;
2645 int status = -ENOSYS;
2646 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002647 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002648 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2650 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2651 else
2652 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2653 pthread_mutex_unlock(&out->lock);
2654 }
2655 return status;
2656}
2657
2658static int out_flush(struct audio_stream_out* stream)
2659{
2660 struct stream_out *out = (struct stream_out *)stream;
2661 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002662 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002663 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002664 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002665 stop_compressed_output_l(out);
2666 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002667 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668 return 0;
2669 }
2670 return -ENOSYS;
2671}
2672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673/** audio_stream_in implementation **/
2674static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2675{
2676 struct stream_in *in = (struct stream_in *)stream;
2677
2678 return in->config.rate;
2679}
2680
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002681static int in_set_sample_rate(struct audio_stream *stream __unused,
2682 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
2684 return -ENOSYS;
2685}
2686
2687static size_t in_get_buffer_size(const struct audio_stream *stream)
2688{
2689 struct stream_in *in = (struct stream_in *)stream;
2690
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002691 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2692 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002693 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2694 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002695
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002696 return in->config.period_size *
2697 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698}
2699
2700static uint32_t in_get_channels(const struct audio_stream *stream)
2701{
2702 struct stream_in *in = (struct stream_in *)stream;
2703
2704 return in->channel_mask;
2705}
2706
2707static audio_format_t in_get_format(const struct audio_stream *stream)
2708{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002709 struct stream_in *in = (struct stream_in *)stream;
2710
2711 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712}
2713
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002714static int in_set_format(struct audio_stream *stream __unused,
2715 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716{
2717 return -ENOSYS;
2718}
2719
2720static int in_standby(struct audio_stream *stream)
2721{
2722 struct stream_in *in = (struct stream_in *)stream;
2723 struct audio_device *adev = in->dev;
2724 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302725 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2726 stream, in->usecase, use_case_table[in->usecase]);
2727
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002728 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2729 /* Ignore standby in case of voip call because the voip input
2730 * stream is closed in adev_close_input_stream()
2731 */
2732 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2733 return status;
2734 }
2735
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002736 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002737 if (!in->standby && in->is_st_session) {
2738 ALOGD("%s: sound trigger pcm stop lab", __func__);
2739 audio_extn_sound_trigger_stop_lab(in);
2740 in->standby = 1;
2741 }
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002744 if (adev->adm_deregister_stream)
2745 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2746
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002747 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002749 if (in->pcm) {
2750 pcm_close(in->pcm);
2751 in->pcm = NULL;
2752 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002754 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 }
2756 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002757 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 return status;
2759}
2760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002761static int in_dump(const struct audio_stream *stream __unused,
2762 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763{
2764 return 0;
2765}
2766
2767static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2768{
2769 struct stream_in *in = (struct stream_in *)stream;
2770 struct audio_device *adev = in->dev;
2771 struct str_parms *parms;
2772 char *str;
2773 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002774 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302776 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 parms = str_parms_create_str(kvpairs);
2778
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302779 if (!parms)
2780 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002781 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002782 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002783
2784 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2785 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 val = atoi(value);
2787 /* no audio source uses val == 0 */
2788 if ((in->source != val) && (val != 0)) {
2789 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002790 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2791 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2792 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002793 (in->config.rate == 8000 || in->config.rate == 16000 ||
2794 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002795 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002796 err = voice_extn_compress_voip_open_input_stream(in);
2797 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002798 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002799 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002800 }
2801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 }
2803 }
2804
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002805 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2806 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002808 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 in->device = val;
2810 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002811 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002812 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 }
2814 }
2815
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002816done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002818 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819
2820 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302821error:
Eric Laurent994a6932013-07-17 11:51:42 -07002822 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 return ret;
2824}
2825
2826static char* in_get_parameters(const struct audio_stream *stream,
2827 const char *keys)
2828{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002829 struct stream_in *in = (struct stream_in *)stream;
2830 struct str_parms *query = str_parms_create_str(keys);
2831 char *str;
2832 char value[256];
2833 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002834
2835 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002836 if (reply) {
2837 str_parms_destroy(reply);
2838 }
2839 if (query) {
2840 str_parms_destroy(query);
2841 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002842 ALOGE("in_get_parameters: failed to create query or reply");
2843 return NULL;
2844 }
2845
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002846 ALOGV("%s: enter: keys - %s", __func__, keys);
2847
2848 voice_extn_in_get_parameters(in, query, reply);
2849
2850 str = str_parms_to_str(reply);
2851 str_parms_destroy(query);
2852 str_parms_destroy(reply);
2853
2854 ALOGV("%s: exit: returns - %s", __func__, str);
2855 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856}
2857
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002858static int in_set_gain(struct audio_stream_in *stream __unused,
2859 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860{
2861 return 0;
2862}
2863
2864static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2865 size_t bytes)
2866{
2867 struct stream_in *in = (struct stream_in *)stream;
2868 struct audio_device *adev = in->dev;
2869 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302870 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002872 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302873
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002874 if (in->is_st_session) {
2875 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2876 /* Read from sound trigger HAL */
2877 audio_extn_sound_trigger_read(in, buffer, bytes);
2878 pthread_mutex_unlock(&in->lock);
2879 return bytes;
2880 }
2881
Ashish Jainbbce4322016-02-16 13:25:27 +05302882 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002883 ALOGD(" %s: sound card is not active/SSR state", __func__);
2884 ret= -EIO;;
2885 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302886 }
2887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002889 pthread_mutex_lock(&adev->lock);
2890 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2891 ret = voice_extn_compress_voip_start_input_stream(in);
2892 else
2893 ret = start_input_stream(in);
2894 pthread_mutex_unlock(&adev->lock);
2895 if (ret != 0) {
2896 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 }
2898 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002899 if (adev->adm_register_input_stream)
2900 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002903 if (adev->adm_request_focus)
2904 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002907 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002908 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002909 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2910 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002911 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2912 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002913 else
2914 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302915 if (ret < 0)
2916 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
2918
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002919 if (adev->adm_abandon_focus)
2920 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 /*
2923 * Instead of writing zeroes here, we could trust the hardware
2924 * to always provide zeroes when muted.
2925 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302926 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2927 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 memset(buffer, 0, bytes);
2929
2930exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302931 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302932 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002933 if (-ENETRESET == ret)
2934 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 pthread_mutex_unlock(&in->lock);
2937
2938 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302939 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302940 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302941 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302942 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302943 in->standby = true;
2944 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302945 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002947 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302948 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302949 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 }
2951 return bytes;
2952}
2953
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002954static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955{
2956 return 0;
2957}
2958
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002959static int add_remove_audio_effect(const struct audio_stream *stream,
2960 effect_handle_t effect,
2961 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002963 struct stream_in *in = (struct stream_in *)stream;
2964 int status = 0;
2965 effect_descriptor_t desc;
2966
2967 status = (*effect)->get_descriptor(effect, &desc);
2968 if (status != 0)
2969 return status;
2970
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002971 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002972 pthread_mutex_lock(&in->dev->lock);
2973 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2974 in->enable_aec != enable &&
2975 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2976 in->enable_aec = enable;
2977 if (!in->standby)
2978 select_devices(in->dev, in->usecase);
2979 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002980 if (in->enable_ns != enable &&
2981 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2982 in->enable_ns = enable;
2983 if (!in->standby)
2984 select_devices(in->dev, in->usecase);
2985 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002986 pthread_mutex_unlock(&in->dev->lock);
2987 pthread_mutex_unlock(&in->lock);
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 return 0;
2990}
2991
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002992static int in_add_audio_effect(const struct audio_stream *stream,
2993 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994{
Eric Laurent994a6932013-07-17 11:51:42 -07002995 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002996 return add_remove_audio_effect(stream, effect, true);
2997}
2998
2999static int in_remove_audio_effect(const struct audio_stream *stream,
3000 effect_handle_t effect)
3001{
Eric Laurent994a6932013-07-17 11:51:42 -07003002 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003003 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004}
3005
3006static int adev_open_output_stream(struct audio_hw_device *dev,
3007 audio_io_handle_t handle,
3008 audio_devices_t devices,
3009 audio_output_flags_t flags,
3010 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003011 struct audio_stream_out **stream_out,
3012 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013{
3014 struct audio_device *adev = (struct audio_device *)dev;
3015 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003016 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003017 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303020
3021 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3022 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003023 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303024 return -EINVAL;
3025 }
3026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3028
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303029 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3030 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3031 devices, flags, &out->stream);
3032
3033
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003034 if (!out) {
3035 return -ENOMEM;
3036 }
3037
Haynes Mathew George204045b2015-02-25 20:32:03 -08003038 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003039 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003040 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 if (devices == AUDIO_DEVICE_NONE)
3043 devices = AUDIO_DEVICE_OUT_SPEAKER;
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 out->flags = flags;
3046 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003047 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003048 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 out->sample_rate = config->sample_rate;
3050 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3051 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003052 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003053 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003054 out->non_blocking = 0;
3055 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056
3057 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003058 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303059 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3060 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003061 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3062 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3063
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003065 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3066 ret = read_hdmi_channel_masks(out);
3067
3068 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3069 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003070 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003071 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003072 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003073
3074 if (config->sample_rate == 0)
3075 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3076 if (config->channel_mask == 0)
3077 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3078
3079 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3082 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003084 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003086 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3087 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003088 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003089 ret = voice_extn_compress_voip_open_output_stream(out);
3090 if (ret != 0) {
3091 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3092 __func__, ret);
3093 goto error_open;
3094 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003095 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3096 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3099 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3100 ALOGE("%s: Unsupported Offload information", __func__);
3101 ret = -EINVAL;
3102 goto error_open;
3103 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003104
3105 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3106 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3107 ALOGV("read and update_pass through formats");
3108 ret = audio_extn_dolby_update_passt_formats(adev, out);
3109 if(ret != 0) {
3110 goto error_open;
3111 }
3112 if(config->offload_info.format == 0)
3113 config->offload_info.format = out->supported_formats[0];
3114 }
3115
Mingming Yin90310102013-11-13 16:57:00 -08003116 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003117 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003118 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 ret = -EINVAL;
3120 goto error_open;
3121 }
3122
3123 out->compr_config.codec = (struct snd_codec *)
3124 calloc(1, sizeof(struct snd_codec));
3125
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003126 if (!out->compr_config.codec) {
3127 ret = -ENOMEM;
3128 goto error_open;
3129 }
3130
vivek mehta0ea887a2015-08-26 14:01:20 -07003131 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003132 out->usecase = get_offload_usecase(adev, true);
3133 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003134 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003135 out->stream.set_callback = out_set_callback;
3136 out->stream.pause = out_pause;
3137 out->stream.resume = out_resume;
3138 out->stream.drain = out_drain;
3139 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003140 out->usecase = get_offload_usecase(adev, false);
3141 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003142 }
vivek mehta446c3962015-09-14 10:57:35 -07003143
3144 if (out->usecase == USECASE_INVALID) {
Alexy Josephb1379942016-01-29 15:49:38 -08003145 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
vivek mehta446c3962015-09-14 10:57:35 -07003146 ret = -EEXIST;
3147 goto error_open;
3148 }
3149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 if (config->offload_info.channel_mask)
3151 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003152 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003154 config->offload_info.channel_mask = config->channel_mask;
3155 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003156 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157 out->sample_rate = config->offload_info.sample_rate;
3158
Mingming Yin3ee55c62014-08-04 14:23:35 -07003159 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003161 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003162 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003163 audio_extn_dolby_get_snd_codec_id(adev, out,
3164 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003165 else
3166 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003168
3169 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3170 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003171 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003172 platform_get_pcm_offload_buffer_size(&config->offload_info);
3173 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3174 out->compr_config.fragment_size =
3175 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003176 } else {
3177 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003178 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003179 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3181 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003182 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183 out->compr_config.codec->bit_rate =
3184 config->offload_info.bit_rate;
3185 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003186 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303188 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003189 /*TODO: Do we need to change it for passthrough */
3190 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191
Manish Dewangana6fc5442015-08-24 20:30:31 +05303192 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3193 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3194 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3195 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003196 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3197 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003198 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003199 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003200 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3201 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003202
Mingming Yin3ee55c62014-08-04 14:23:35 -07003203 if (out->bit_width == 24) {
3204 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3205 }
3206
Amit Shekhar6f461b12014-08-01 14:52:58 -07003207 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303208 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3211 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003212
Mingming Yin497419f2015-07-01 16:57:32 -07003213 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003214 //this flag is set from framework only if its for PCM formats
3215 //no need to check for PCM format again
3216 out->non_blocking = 0;
3217 out->use_small_bufs = true;
3218 ALOGI("Keep write blocking for small buff: non_blockling %d",
3219 out->non_blocking);
3220 }
3221
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003222 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303223 out->send_next_track_params = false;
3224 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003225 out->offload_state = OFFLOAD_STATE_IDLE;
3226 out->playback_started = 0;
3227
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003228 audio_extn_dts_create_state_notifier_node(out->usecase);
3229
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003230 create_offload_callback_thread(out);
3231 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3232 __func__, config->offload_info.version,
3233 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003234 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003235 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003236 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3237 ret = voice_check_and_set_incall_music_usecase(adev, out);
3238 if (ret != 0) {
3239 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3240 __func__, ret);
3241 goto error_open;
3242 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003243 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3244 if (config->sample_rate == 0)
3245 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3246 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3247 config->sample_rate != 8000) {
3248 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3249 ret = -EINVAL;
3250 goto error_open;
3251 }
3252 out->sample_rate = config->sample_rate;
3253 out->config.rate = config->sample_rate;
3254 if (config->format == AUDIO_FORMAT_DEFAULT)
3255 config->format = AUDIO_FORMAT_PCM_16_BIT;
3256 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3257 config->format = AUDIO_FORMAT_PCM_16_BIT;
3258 ret = -EINVAL;
3259 goto error_open;
3260 }
3261 out->format = config->format;
3262 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3263 out->config = pcm_config_afe_proxy_playback;
3264 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003265 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3266 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3267 out->config = pcm_config_low_latency;
3268 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003269 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003270 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3272 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003274 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3275 format = AUDIO_FORMAT_PCM_16_BIT;
3276 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3277 out->config = pcm_config_deep_buffer;
3278 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003279 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003280 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003281 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003282 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003283 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003284 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 }
3286
Amit Shekhar1d896042014-10-03 13:16:09 -07003287 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3288 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003289 /* TODO remove this hardcoding and check why width is zero*/
3290 if (out->bit_width == 0)
3291 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003292 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3293 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003294 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303295 out->bit_width, out->channel_mask,
3296 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003297 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3298 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3299 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003300 if(adev->primary_output == NULL)
3301 adev->primary_output = out;
3302 else {
3303 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003304 ret = -EEXIST;
3305 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003306 }
3307 }
3308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 /* Check if this usecase is already existing */
3310 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003311 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3312 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003315 ret = -EEXIST;
3316 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 }
3318 pthread_mutex_unlock(&adev->lock);
3319
3320 out->stream.common.get_sample_rate = out_get_sample_rate;
3321 out->stream.common.set_sample_rate = out_set_sample_rate;
3322 out->stream.common.get_buffer_size = out_get_buffer_size;
3323 out->stream.common.get_channels = out_get_channels;
3324 out->stream.common.get_format = out_get_format;
3325 out->stream.common.set_format = out_set_format;
3326 out->stream.common.standby = out_standby;
3327 out->stream.common.dump = out_dump;
3328 out->stream.common.set_parameters = out_set_parameters;
3329 out->stream.common.get_parameters = out_get_parameters;
3330 out->stream.common.add_audio_effect = out_add_audio_effect;
3331 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3332 out->stream.get_latency = out_get_latency;
3333 out->stream.set_volume = out_set_volume;
3334 out->stream.write = out_write;
3335 out->stream.get_render_position = out_get_render_position;
3336 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003337 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003340 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003341 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342
3343 config->format = out->stream.common.get_format(&out->stream.common);
3344 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3345 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3346
3347 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303348 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003349 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003350
3351 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3352 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3353 popcount(out->channel_mask), out->playback_started);
3354
Eric Laurent994a6932013-07-17 11:51:42 -07003355 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003357
3358error_open:
3359 free(out);
3360 *stream_out = NULL;
3361 ALOGD("%s: exit: ret %d", __func__, ret);
3362 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363}
3364
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003365static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 struct audio_stream_out *stream)
3367{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 struct stream_out *out = (struct stream_out *)stream;
3369 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003370 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303372 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3373
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003374 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303375 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003376 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303377 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003378 if(ret != 0)
3379 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3380 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003381 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003382 out_standby(&stream->common);
3383
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003384 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003385 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003387 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 if (out->compr_config.codec != NULL)
3389 free(out->compr_config.codec);
3390 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003391
3392 if (adev->voice_tx_output == out)
3393 adev->voice_tx_output = NULL;
3394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 pthread_cond_destroy(&out->cond);
3396 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003398 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003401static void close_compress_sessions(struct audio_device *adev)
3402{
Mingming Yin7b762e72015-03-04 13:47:32 -08003403 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303404 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003405 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003406 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303407
3408 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003409 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303410 if (is_offload_usecase(usecase->id)) {
3411 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003412 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3413 out = usecase->stream.out;
3414 pthread_mutex_unlock(&adev->lock);
3415 out_standby(&out->stream.common);
3416 pthread_mutex_lock(&adev->lock);
3417 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303418 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003419 }
3420 pthread_mutex_unlock(&adev->lock);
3421}
3422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3424{
3425 struct audio_device *adev = (struct audio_device *)dev;
3426 struct str_parms *parms;
3427 char *str;
3428 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003429 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003430 int ret;
3431 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003433 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303436 if (!parms)
3437 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003438 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3439 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303440 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303441 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303442 struct listnode *node;
3443 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303444 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303445 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003446 //close compress sessions on OFFLINE status
3447 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303448 } else if (strstr(snd_card_status, "ONLINE")) {
3449 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303450 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003451 //send dts hpx license if enabled
3452 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303453 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303454 }
3455
3456 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003457 status = voice_set_parameters(adev, parms);
3458 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003459 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003461 status = platform_set_parameters(adev->platform, parms);
3462 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003463 goto done;
3464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003465 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3466 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003467 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3469 adev->bluetooth_nrec = true;
3470 else
3471 adev->bluetooth_nrec = false;
3472 }
3473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003474 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3475 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3477 adev->screen_off = false;
3478 else
3479 adev->screen_off = true;
3480 }
3481
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003482 ret = str_parms_get_int(parms, "rotation", &val);
3483 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003484 bool reverse_speakers = false;
3485 switch(val) {
3486 // FIXME: note that the code below assumes that the speakers are in the correct placement
3487 // relative to the user when the device is rotated 90deg from its default rotation. This
3488 // assumption is device-specific, not platform-specific like this code.
3489 case 270:
3490 reverse_speakers = true;
3491 break;
3492 case 0:
3493 case 90:
3494 case 180:
3495 break;
3496 default:
3497 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003498 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003499 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003500 if (status == 0) {
3501 if (adev->speaker_lr_swap != reverse_speakers) {
3502 adev->speaker_lr_swap = reverse_speakers;
3503 // only update the selected device if there is active pcm playback
3504 struct audio_usecase *usecase;
3505 struct listnode *node;
3506 list_for_each(node, &adev->usecase_list) {
3507 usecase = node_to_item(node, struct audio_usecase, list);
3508 if (usecase->type == PCM_PLAYBACK) {
3509 select_devices(adev, usecase->id);
3510 break;
3511 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003512 }
3513 }
3514 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003515 }
3516
Mingming Yin514a8bc2014-07-29 15:22:21 -07003517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3518 if (ret >= 0) {
3519 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3520 adev->bt_wb_speech_enabled = true;
3521 else
3522 adev->bt_wb_speech_enabled = false;
3523 }
3524
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003525 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3526 if (ret >= 0) {
3527 val = atoi(value);
3528 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3529 ALOGV("cache new edid");
3530 platform_cache_edid(adev->platform);
3531 }
3532 }
3533
3534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3535 if (ret >= 0) {
3536 val = atoi(value);
3537 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3538 ALOGV("invalidate cached edid");
3539 platform_invalidate_edid(adev->platform);
3540 }
3541 }
3542
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003543 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003544
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003545done:
3546 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003547 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303548error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003549 ALOGV("%s: exit with code(%d)", __func__, status);
3550 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551}
3552
3553static char* adev_get_parameters(const struct audio_hw_device *dev,
3554 const char *keys)
3555{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003556 struct audio_device *adev = (struct audio_device *)dev;
3557 struct str_parms *reply = str_parms_create();
3558 struct str_parms *query = str_parms_create_str(keys);
3559 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303560 char value[256] = {0};
3561 int ret = 0;
3562
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003563 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003564 if (reply) {
3565 str_parms_destroy(reply);
3566 }
3567 if (query) {
3568 str_parms_destroy(query);
3569 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003570 ALOGE("adev_get_parameters: failed to create query or reply");
3571 return NULL;
3572 }
3573
Naresh Tannirud7205b62014-06-20 02:54:48 +05303574 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3575 sizeof(value));
3576 if (ret >=0) {
3577 int val = 1;
3578 pthread_mutex_lock(&adev->snd_card_status.lock);
3579 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3580 val = 0;
3581 pthread_mutex_unlock(&adev->snd_card_status.lock);
3582 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3583 goto exit;
3584 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003585
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003586 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003587 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003588 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003589 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303590 pthread_mutex_unlock(&adev->lock);
3591
Naresh Tannirud7205b62014-06-20 02:54:48 +05303592exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003593 str = str_parms_to_str(reply);
3594 str_parms_destroy(query);
3595 str_parms_destroy(reply);
3596
3597 ALOGV("%s: exit: returns - %s", __func__, str);
3598 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599}
3600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003601static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602{
3603 return 0;
3604}
3605
3606static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3607{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003608 int ret;
3609 struct audio_device *adev = (struct audio_device *)dev;
3610 pthread_mutex_lock(&adev->lock);
3611 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003612 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003613 pthread_mutex_unlock(&adev->lock);
3614 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615}
3616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003617static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3618 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619{
3620 return -ENOSYS;
3621}
3622
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003623static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3624 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625{
3626 return -ENOSYS;
3627}
3628
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003629static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3630 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631{
3632 return -ENOSYS;
3633}
3634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003635static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3636 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637{
3638 return -ENOSYS;
3639}
3640
3641static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3642{
3643 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 pthread_mutex_lock(&adev->lock);
3646 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003647 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003649 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003650 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003651 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003652 adev->current_call_output = NULL;
3653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 }
3655 pthread_mutex_unlock(&adev->lock);
3656 return 0;
3657}
3658
3659static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3660{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003661 int ret;
3662
3663 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003664 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003665 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3666 pthread_mutex_unlock(&adev->lock);
3667
3668 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
3671static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3672{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003673 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 return 0;
3675}
3676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003677static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 const struct audio_config *config)
3679{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003680 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003682 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3683 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684}
3685
3686static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003687 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 audio_devices_t devices,
3689 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003690 struct audio_stream_in **stream_in,
3691 audio_input_flags_t flags __unused,
3692 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003693 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694{
3695 struct audio_device *adev = (struct audio_device *)dev;
3696 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003697 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003698 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003699 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 *stream_in = NULL;
3702 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3703 return -EINVAL;
3704
3705 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003706
3707 if (!in) {
3708 ALOGE("failed to allocate input stream");
3709 return -ENOMEM;
3710 }
3711
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303712 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003713 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3714 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003716 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003717 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 in->stream.common.get_sample_rate = in_get_sample_rate;
3720 in->stream.common.set_sample_rate = in_set_sample_rate;
3721 in->stream.common.get_buffer_size = in_get_buffer_size;
3722 in->stream.common.get_channels = in_get_channels;
3723 in->stream.common.get_format = in_get_format;
3724 in->stream.common.set_format = in_set_format;
3725 in->stream.common.standby = in_standby;
3726 in->stream.common.dump = in_dump;
3727 in->stream.common.set_parameters = in_set_parameters;
3728 in->stream.common.get_parameters = in_get_parameters;
3729 in->stream.common.add_audio_effect = in_add_audio_effect;
3730 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3731 in->stream.set_gain = in_set_gain;
3732 in->stream.read = in_read;
3733 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3734
3735 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003736 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 in->standby = 1;
3739 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003740 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003741 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742
3743 /* Update config params with the requested sample rate and channels */
3744 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003745 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3746 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3747 is_low_latency = true;
3748#if LOW_LATENCY_CAPTURE_USE_CASE
3749 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3750#endif
3751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003754 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003756 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303757 if (adev->mode != AUDIO_MODE_IN_CALL) {
3758 ret = -EINVAL;
3759 goto err_open;
3760 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003761 if (config->sample_rate == 0)
3762 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3763 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3764 config->sample_rate != 8000) {
3765 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3766 ret = -EINVAL;
3767 goto err_open;
3768 }
3769 if (config->format == AUDIO_FORMAT_DEFAULT)
3770 config->format = AUDIO_FORMAT_PCM_16_BIT;
3771 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3772 config->format = AUDIO_FORMAT_PCM_16_BIT;
3773 ret = -EINVAL;
3774 goto err_open;
3775 }
3776
3777 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3778 in->config = pcm_config_afe_proxy_record;
3779 in->config.channels = channel_count;
3780 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303781 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3782 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003783 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003784 audio_extn_compr_cap_format_supported(config->format) &&
3785 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003786 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003787 } else {
3788 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003789 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003790 buffer_size = get_input_buffer_size(config->sample_rate,
3791 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003792 channel_count,
3793 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003794 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003795 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3796 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3797 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003798 (in->config.rate == 8000 || in->config.rate == 16000 ||
3799 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003800 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3801 voice_extn_compress_voip_open_input_stream(in);
3802 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003805 /* This stream could be for sound trigger lab,
3806 get sound trigger pcm if present */
3807 audio_extn_sound_trigger_check_and_get_session(in);
3808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003810 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003811 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
3813err_open:
3814 free(in);
3815 *stream_in = NULL;
3816 return ret;
3817}
3818
3819static void adev_close_input_stream(struct audio_hw_device *dev,
3820 struct audio_stream_in *stream)
3821{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003822 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003823 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003824 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303825
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303826 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003827
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303828 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003829 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303830
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003831 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303832 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003833 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303834 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003835 if (ret != 0)
3836 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3837 __func__, ret);
3838 } else
3839 in_standby(&stream->common);
3840
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003841 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003842 audio_extn_ssr_deinit();
3843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844
Mingming Yine62d7842013-10-25 16:26:03 -07003845 if(audio_extn_compr_cap_enabled() &&
3846 audio_extn_compr_cap_format_supported(in->config.format))
3847 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003848
Mingming Yinfd7607b2016-01-22 12:48:44 -08003849 if (in->is_st_session) {
3850 ALOGV("%s: sound trigger pcm stop lab", __func__);
3851 audio_extn_sound_trigger_stop_lab(in);
3852 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003853 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 return;
3855}
3856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003857static int adev_dump(const audio_hw_device_t *device __unused,
3858 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859{
3860 return 0;
3861}
3862
3863static int adev_close(hw_device_t *device)
3864{
3865 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003866
3867 if (!adev)
3868 return 0;
3869
3870 pthread_mutex_lock(&adev_init_lock);
3871
3872 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003873 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003874 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003875 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003876 audio_route_free(adev->audio_route);
3877 free(adev->snd_dev_ref_cnt);
3878 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003879 if (adev->adm_deinit)
3880 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003881 free(device);
3882 adev = NULL;
3883 }
3884 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 return 0;
3887}
3888
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003889/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3890 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3891 * just that it _might_ work.
3892 */
3893static int period_size_is_plausible_for_low_latency(int period_size)
3894{
3895 switch (period_size) {
3896 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003897 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003898 case 240:
3899 case 320:
3900 case 480:
3901 return 1;
3902 default:
3903 return 0;
3904 }
3905}
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907static int adev_open(const hw_module_t *module, const char *name,
3908 hw_device_t **device)
3909{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003910 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003912 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3914
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003915 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003916 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003917 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003918 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003919 ALOGD("%s: returning existing instance of adev", __func__);
3920 ALOGD("%s: exit", __func__);
3921 pthread_mutex_unlock(&adev_init_lock);
3922 return 0;
3923 }
3924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 adev = calloc(1, sizeof(struct audio_device));
3926
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003927 if (!adev) {
3928 pthread_mutex_unlock(&adev_init_lock);
3929 return -ENOMEM;
3930 }
3931
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003932 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3935 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3936 adev->device.common.module = (struct hw_module_t *)module;
3937 adev->device.common.close = adev_close;
3938
3939 adev->device.init_check = adev_init_check;
3940 adev->device.set_voice_volume = adev_set_voice_volume;
3941 adev->device.set_master_volume = adev_set_master_volume;
3942 adev->device.get_master_volume = adev_get_master_volume;
3943 adev->device.set_master_mute = adev_set_master_mute;
3944 adev->device.get_master_mute = adev_get_master_mute;
3945 adev->device.set_mode = adev_set_mode;
3946 adev->device.set_mic_mute = adev_set_mic_mute;
3947 adev->device.get_mic_mute = adev_get_mic_mute;
3948 adev->device.set_parameters = adev_set_parameters;
3949 adev->device.get_parameters = adev_get_parameters;
3950 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3951 adev->device.open_output_stream = adev_open_output_stream;
3952 adev->device.close_output_stream = adev_close_output_stream;
3953 adev->device.open_input_stream = adev_open_input_stream;
3954 adev->device.close_input_stream = adev_close_input_stream;
3955 adev->device.dump = adev_dump;
3956
3957 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003959 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003960 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003963 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003964 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003965 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003966 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003967 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003968 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003969 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303970 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303971 adev->perf_lock_opts[0] = 0x101;
3972 adev->perf_lock_opts[1] = 0x20E;
3973 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303974
3975 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3976 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003978 adev->platform = platform_init(adev);
3979 if (!adev->platform) {
3980 free(adev->snd_dev_ref_cnt);
3981 free(adev);
3982 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3983 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003984 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003985 return -EINVAL;
3986 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003987
Naresh Tanniru4c630392014-05-12 01:05:52 +05303988 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3989
Eric Laurentc4aef752013-09-12 17:45:53 -07003990 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3991 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3992 if (adev->visualizer_lib == NULL) {
3993 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3994 } else {
3995 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3996 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003997 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003998 "visualizer_hal_start_output");
3999 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004000 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004001 "visualizer_hal_stop_output");
4002 }
4003 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004004 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004005 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004006
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004007 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4008 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4009 if (adev->offload_effects_lib == NULL) {
4010 ALOGE("%s: DLOPEN failed for %s", __func__,
4011 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4012 } else {
4013 ALOGV("%s: DLOPEN successful for %s", __func__,
4014 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4015 adev->offload_effects_start_output =
4016 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4017 "offload_effects_bundle_hal_start_output");
4018 adev->offload_effects_stop_output =
4019 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4020 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004021 adev->offload_effects_set_hpx_state =
4022 (int (*)(bool))dlsym(adev->offload_effects_lib,
4023 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304024 adev->offload_effects_get_parameters =
4025 (void (*)(struct str_parms *, struct str_parms *))
4026 dlsym(adev->offload_effects_lib,
4027 "offload_effects_bundle_get_parameters");
4028 adev->offload_effects_set_parameters =
4029 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4030 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004031 }
4032 }
4033
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004034 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4035 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4036 if (adev->adm_lib == NULL) {
4037 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4038 } else {
4039 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4040 adev->adm_init = (adm_init_t)
4041 dlsym(adev->adm_lib, "adm_init");
4042 adev->adm_deinit = (adm_deinit_t)
4043 dlsym(adev->adm_lib, "adm_deinit");
4044 adev->adm_register_input_stream = (adm_register_input_stream_t)
4045 dlsym(adev->adm_lib, "adm_register_input_stream");
4046 adev->adm_register_output_stream = (adm_register_output_stream_t)
4047 dlsym(adev->adm_lib, "adm_register_output_stream");
4048 adev->adm_deregister_stream = (adm_deregister_stream_t)
4049 dlsym(adev->adm_lib, "adm_deregister_stream");
4050 adev->adm_request_focus = (adm_request_focus_t)
4051 dlsym(adev->adm_lib, "adm_request_focus");
4052 adev->adm_abandon_focus = (adm_abandon_focus_t)
4053 dlsym(adev->adm_lib, "adm_abandon_focus");
4054 }
4055 }
4056
Mingming Yin514a8bc2014-07-29 15:22:21 -07004057 adev->bt_wb_speech_enabled = false;
4058
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004059 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 *device = &adev->device.common;
4061
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004062 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4063 &adev->streams_output_cfg_list);
4064
Kiran Kandi910e1862013-10-29 13:29:42 -07004065 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004066
4067 char value[PROPERTY_VALUE_MAX];
4068 int trial;
4069 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4070 trial = atoi(value);
4071 if (period_size_is_plausible_for_low_latency(trial)) {
4072 pcm_config_low_latency.period_size = trial;
4073 pcm_config_low_latency.start_threshold = trial / 4;
4074 pcm_config_low_latency.avail_min = trial / 4;
4075 configured_low_latency_capture_period_size = trial;
4076 }
4077 }
4078 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4079 trial = atoi(value);
4080 if (period_size_is_plausible_for_low_latency(trial)) {
4081 configured_low_latency_capture_period_size = trial;
4082 }
4083 }
4084
vivek mehta446c3962015-09-14 10:57:35 -07004085 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004086 pthread_mutex_unlock(&adev_init_lock);
4087
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004088 if (adev->adm_init)
4089 adev->adm_data = adev->adm_init();
4090
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304091 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004092 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 return 0;
4094}
4095
4096static struct hw_module_methods_t hal_module_methods = {
4097 .open = adev_open,
4098};
4099
4100struct audio_module HAL_MODULE_INFO_SYM = {
4101 .common = {
4102 .tag = HARDWARE_MODULE_TAG,
4103 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4104 .hal_api_version = HARDWARE_HAL_API_VERSION,
4105 .id = AUDIO_HARDWARE_MODULE_ID,
4106 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004107 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 .methods = &hal_module_methods,
4109 },
4110};