blob: 0526e9baad2c606f4af03f88b4e16e24912e3c26 [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{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530508
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700509 if (audio_extn_spkr_prot_is_enabled())
510 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 /* start usb playback thread */
512 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
513 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
514 audio_extn_usb_start_playback(adev);
515
516 /* start usb capture thread */
517 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
518 audio_extn_usb_start_capture(adev);
519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
521 audio_extn_spkr_prot_is_enabled()) {
522 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 adev->snd_dev_ref_cnt[snd_device]--;
524 return -EINVAL;
525 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200526 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800527 if (audio_extn_spkr_prot_start_processing(snd_device)) {
528 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200529 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800530 return -EINVAL;
531 }
532 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700533 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530550
551 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
552 !adev->native_playback_enabled &&
553 audio_is_true_native_stream_active(adev)) {
554 ALOGD("%s: %d: napb: enabling native mode in hardware",
555 __func__, __LINE__);
556 audio_route_apply_and_update_path(adev->audio_route,
557 "true-native-mode");
558 adev->native_playback_enabled = true;
559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700564int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700565 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
568
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 if (snd_device < SND_DEVICE_MIN ||
570 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800571 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 return -EINVAL;
573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
575 ALOGE("%s: device ref cnt is already 0", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
582 ALOGE("%s: Invalid sound device returned", __func__);
583 return -EINVAL;
584 }
585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700587 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588 /* exit usb play back thread */
589 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
590 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
591 audio_extn_usb_stop_playback();
592
593 /* exit usb capture thread */
594 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700595 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800596
597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ashish Jain81eb2a82015-05-13 10:52:34 +0530604 if (snd_device == SND_DEVICE_OUT_HDMI)
605 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530606 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
607 adev->native_playback_enabled) {
608 ALOGD("%s: %d: napb: disabling native mode in hardware",
609 __func__, __LINE__);
610 audio_route_reset_and_update_path(adev->audio_route,
611 "true-native-mode");
612 adev->native_playback_enabled = false;
613 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530614
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200615 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700616 audio_extn_sound_trigger_update_device_status(snd_device,
617 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530618 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800619 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622 return 0;
623}
624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625static void check_usecases_codec_backend(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
628{
629 struct listnode *node;
630 struct audio_usecase *usecase;
631 bool switch_device[AUDIO_USECASE_MAX];
632 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 int backend_idx = DEFAULT_CODEC_BACKEND;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635
636 /*
637 * This function is to make sure that all the usecases that are active on
638 * the hardware codec backend are always routed to any one device that is
639 * handled by the hardware codec.
640 * For example, if low-latency and deep-buffer usecases are currently active
641 * on speaker and out_set_parameters(headset) is received on low-latency
642 * output, then we have to make sure deep-buffer is also switched to headset,
643 * because of the limitation that both the devices cannot be enabled
644 * at the same time as they share the same backend.
645 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700646 /*
647 * This call is to check if we need to force routing for a particular stream
648 * If there is a backend configuration change for the device when a
649 * new stream starts, then ADM needs to be closed and re-opened with the new
650 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700652 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
654 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530655
656 ALOGD("%s:becf: force routing %d", __func__, force_routing);
657
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800660 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800661 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 for (i = 0; i < AUDIO_USECASE_MAX; i++)
663 switch_device[i] = false;
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667
668 if (usecase == uc_info)
669 continue;
670 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
673 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
674 __func__, i, backend_idx, usecase_backend_idx,
675 platform_get_snd_device_name(snd_device),
676 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800677
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800678 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700679 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
681 usecase_backend_idx == backend_idx) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530682 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
683 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700684 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 switch_device[usecase->id] = true;
687 num_uc_to_switch++;
688 }
689 }
690
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
692 num_uc_to_switch);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530697 /* Make sure the previous devices to be disabled first and then enable the
698 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 list_for_each(node, &adev->usecase_list) {
700 usecase = node_to_item(node, struct audio_usecase, list);
701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
705
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 /* Re-route all the usecases on the shared backend other than the
714 specified usecase to new snd devices */
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530717 /* Update the out_snd_device only for the usecases that are enabled here */
718 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
719 usecase->out_snd_device = snd_device;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530720 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
721 use_case_table[usecase->id],
722 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530723 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 }
725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727}
728
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729static void check_and_route_capture_usecases(struct audio_device *adev,
730 struct audio_usecase *uc_info,
731 snd_device_t snd_device)
732{
733 struct listnode *node;
734 struct audio_usecase *usecase;
735 bool switch_device[AUDIO_USECASE_MAX];
736 int i, num_uc_to_switch = 0;
737
738 /*
739 * This function is to make sure that all the active capture usecases
740 * are always routed to the same input sound device.
741 * For example, if audio-record and voice-call usecases are currently
742 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
743 * is received for voice call then we have to make sure that audio-record
744 * usecase is also switched to earpiece i.e. voice-dmic-ef,
745 * because of the limitation that two devices cannot be enabled
746 * at the same time if they share the same backend.
747 */
748 for (i = 0; i < AUDIO_USECASE_MAX; i++)
749 switch_device[i] = false;
750
751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700755 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700756 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530757 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
758 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700759 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
761 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700762 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700763 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 switch_device[usecase->id] = true;
765 num_uc_to_switch++;
766 }
767 }
768
769 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700770 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530772 /* Make sure the previous devices to be disabled first and then enable the
773 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 list_for_each(node, &adev->usecase_list) {
775 usecase = node_to_item(node, struct audio_usecase, list);
776 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700777 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800778 }
779 }
780
781 list_for_each(node, &adev->usecase_list) {
782 usecase = node_to_item(node, struct audio_usecase, list);
783 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700784 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700785 }
786 }
787
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700788 /* Re-route all the usecases on the shared backend other than the
789 specified usecase to new snd devices */
790 list_for_each(node, &adev->usecase_list) {
791 usecase = node_to_item(node, struct audio_usecase, list);
792 /* Update the in_snd_device only before enabling the audio route */
793 if (switch_device[usecase->id] ) {
794 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800795 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530796 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 }
798 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800}
801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800802/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700805 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700806 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807
808 switch (channels) {
809 /*
810 * Do not handle stereo output in Multi-channel cases
811 * Stereo case is handled in normal playback path
812 */
813 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700814 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
815 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
816 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
819 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 break;
821 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700822 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
823 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
824 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829 break;
830 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700831 ALOGE("HDMI does not support multi channel playback");
832 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833 break;
834 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700835 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836}
837
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800838audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
839 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840{
841 struct audio_usecase *usecase;
842 struct listnode *node;
843
844 list_for_each(node, &adev->usecase_list) {
845 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800846 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 ALOGV("%s: usecase id %d", __func__, usecase->id);
848 return usecase->id;
849 }
850 }
851 return USECASE_INVALID;
852}
853
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700854struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700855 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856{
857 struct audio_usecase *usecase;
858 struct listnode *node;
859
860 list_for_each(node, &adev->usecase_list) {
861 usecase = node_to_item(node, struct audio_usecase, list);
862 if (usecase->id == uc_id)
863 return usecase;
864 }
865 return NULL;
866}
867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530868/*
869 * is a true native playback active
870 */
871bool audio_is_true_native_stream_active(struct audio_device *adev)
872{
873 bool active = false;
874 int i = 0;
875 struct listnode *node;
876
877 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
878 ALOGV("%s:napb: not in true mode or non hdphones device",
879 __func__);
880 active = false;
881 goto exit;
882 }
883
884 list_for_each(node, &adev->usecase_list) {
885 struct audio_usecase *uc;
886 uc = node_to_item(node, struct audio_usecase, list);
887 struct stream_out *curr_out =
888 (struct stream_out*) uc->stream.out;
889
890 if (curr_out && PCM_PLAYBACK == uc->type) {
891 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
892 "(%d) device %s", __func__, i++, use_case_table[uc->id],
893 uc->id, curr_out->sample_rate,
894 curr_out->bit_width,
895 platform_get_snd_device_name(uc->out_snd_device));
896
897 if (is_offload_usecase(uc->id) &&
898 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
899 active = true;
900 ALOGD("%s:napb:native stream detected", __func__);
901 }
902 }
903 }
904exit:
905 return active;
906}
907
908
909static bool force_device_switch(struct audio_usecase *usecase)
910{
911 bool ret = false;
912 bool is_it_true_mode = false;
913
914 if (is_offload_usecase(usecase->id) &&
915 (usecase->stream.out) &&
916 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
917 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
918 if ((is_it_true_mode && !adev->native_playback_enabled) ||
919 (!is_it_true_mode && adev->native_playback_enabled)){
920 ret = true;
921 ALOGD("napb: time to toggle native mode");
922 }
923 }
924
925 return ret;
926}
927
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700928int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800930 snd_device_t out_snd_device = SND_DEVICE_NONE;
931 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 struct audio_usecase *usecase = NULL;
933 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800934 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800935 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800936 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800937 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700938 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530940 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 usecase = get_usecase_from_list(adev, uc_id);
943 if (usecase == NULL) {
944 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
945 return -EINVAL;
946 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800948 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800949 (usecase->type == VOIP_CALL) ||
950 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700951 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800952 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700953 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 usecase->devices = usecase->stream.out->devices;
955 } else {
956 /*
957 * If the voice call is active, use the sound devices of voice call usecase
958 * so that it would not result any device switch. All the usecases will
959 * be switched to new device when select_devices() is called for voice call
960 * usecase. This is to avoid switching devices for voice call when
961 * check_usecases_codec_backend() is called below.
962 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800963 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700964 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800965 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700966 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
967 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 in_snd_device = vc_usecase->in_snd_device;
969 out_snd_device = vc_usecase->out_snd_device;
970 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800971 } else if (voice_extn_compress_voip_is_active(adev)) {
972 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700973 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530974 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700975 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800976 in_snd_device = voip_usecase->in_snd_device;
977 out_snd_device = voip_usecase->out_snd_device;
978 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800979 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800980 hfp_ucid = audio_extn_hfp_get_usecase();
981 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700982 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800983 in_snd_device = hfp_usecase->in_snd_device;
984 out_snd_device = hfp_usecase->out_snd_device;
985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 if (usecase->type == PCM_PLAYBACK) {
988 usecase->devices = usecase->stream.out->devices;
989 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700990 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700991 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800992 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700993 if (usecase->stream.out == adev->primary_output &&
994 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800995 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700996 select_devices(adev, adev->active_input->usecase);
997 }
998 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 } else if (usecase->type == PCM_CAPTURE) {
1000 usecase->devices = usecase->stream.in->device;
1001 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001002 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001003 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001004 if (adev->active_input &&
1005 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301006 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1007 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1008 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001009 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001010 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001011 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1012 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001013 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001014 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 }
1017 }
1018
1019 if (out_snd_device == usecase->out_snd_device &&
1020 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301021
1022 if (!force_device_switch(usecase))
1023 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 }
1025
sangwoobc677242013-08-08 16:53:43 +09001026 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001027 out_snd_device, platform_get_snd_device_name(out_snd_device),
1028 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030 /*
1031 * Limitation: While in call, to do a device switch we need to disable
1032 * and enable both RX and TX devices though one of them is same as current
1033 * device.
1034 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001035 if ((usecase->type == VOICE_CALL) &&
1036 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1037 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001038 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001039 }
1040
1041 if (((usecase->type == VOICE_CALL) ||
1042 (usecase->type == VOIP_CALL)) &&
1043 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1044 /* Disable sidetone only if voice/voip call already exists */
1045 if (voice_is_call_state_active(adev) ||
1046 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001047 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001048 }
1049
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050 /* Disable current sound devices */
1051 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001052 disable_audio_route(adev, usecase);
1053 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 }
1055
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001057 disable_audio_route(adev, usecase);
1058 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 }
1060
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001061 /* Applicable only on the targets that has external modem.
1062 * New device information should be sent to modem before enabling
1063 * the devices to reduce in-call device switch time.
1064 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001065 if ((usecase->type == VOICE_CALL) &&
1066 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1067 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001068 status = platform_switch_voice_call_enable_device_config(adev->platform,
1069 out_snd_device,
1070 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001071 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001072
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 /* Enable new sound devices */
1074 if (out_snd_device != SND_DEVICE_NONE) {
1075 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1076 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001077 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 }
1079
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001080 if (in_snd_device != SND_DEVICE_NONE) {
1081 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001082 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084
Avinash Vaish71a8b972014-07-24 15:36:33 +05301085 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001086 status = platform_switch_voice_call_device_post(adev->platform,
1087 out_snd_device,
1088 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301089 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001090 /* Enable sidetone only if voice/voip call already exists */
1091 if (voice_is_call_state_active(adev) ||
1092 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001093 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301094 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001095
sangwoo170731f2013-06-08 15:36:36 +09001096 usecase->in_snd_device = in_snd_device;
1097 usecase->out_snd_device = out_snd_device;
1098
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301099 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001100 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301101 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001102 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301103 usecase->stream.out->flags,
1104 usecase->stream.out->format,
1105 usecase->stream.out->sample_rate,
1106 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301107 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301108 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001109 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301110 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001111
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001112 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001113
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001114 /* Applicable only on the targets that has external modem.
1115 * Enable device command should be sent to modem only after
1116 * enabling voice call mixer controls
1117 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001118 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001119 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1120 out_snd_device,
1121 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301122 ALOGD("%s: done",__func__);
1123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124 return status;
1125}
1126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127static int stop_input_stream(struct stream_in *in)
1128{
1129 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130 struct audio_usecase *uc_info;
1131 struct audio_device *adev = in->dev;
1132
Eric Laurentc8400632013-02-14 19:04:54 -08001133 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134
Eric Laurent994a6932013-07-17 11:51:42 -07001135 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137 uc_info = get_usecase_from_list(adev, in->usecase);
1138 if (uc_info == NULL) {
1139 ALOGE("%s: Could not find the usecase (%d) in the list",
1140 __func__, in->usecase);
1141 return -EINVAL;
1142 }
1143
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001144 /* Close in-call recording streams */
1145 voice_check_and_stop_incall_rec_usecase(adev, in);
1146
Eric Laurent150dbfe2013-02-27 14:31:02 -08001147 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001148 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149
1150 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001151 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001153 list_remove(&uc_info->list);
1154 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155
Eric Laurent994a6932013-07-17 11:51:42 -07001156 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157 return ret;
1158}
1159
1160int start_input_stream(struct stream_in *in)
1161{
1162 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001163 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164 struct audio_usecase *uc_info;
1165 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301166 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167
Mingming Yin2664a5b2015-09-03 10:53:11 -07001168 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1169 if (get_usecase_from_list(adev, usecase) == NULL)
1170 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301171 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1172 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001173
Naresh Tanniru80659832014-06-04 18:17:56 +05301174
1175 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301176 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301177 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301178 goto error_config;
1179 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301180
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001181 /* Check if source matches incall recording usecase criteria */
1182 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1183 if (ret)
1184 goto error_config;
1185 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001186 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1187
1188 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1189 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1190 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1191 goto error_config;
1192 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001193
Eric Laurentb23d5282013-05-14 15:27:20 -07001194 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195 if (in->pcm_device_id < 0) {
1196 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1197 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001198 ret = -EINVAL;
1199 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201
1202 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001203 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001204
1205 if (!uc_info) {
1206 ret = -ENOMEM;
1207 goto error_config;
1208 }
1209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 uc_info->id = in->usecase;
1211 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001212 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001213 uc_info->devices = in->device;
1214 uc_info->in_snd_device = SND_DEVICE_NONE;
1215 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001217 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301218 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1219 adev->perf_lock_opts,
1220 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222
Eric Laurentc8400632013-02-14 19:04:54 -08001223 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001224 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1225
1226 unsigned int flags = PCM_IN;
1227 unsigned int pcm_open_retry_count = 0;
1228
1229 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1230 flags |= PCM_MMAP | PCM_NOIRQ;
1231 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1232 }
1233
1234 while (1) {
1235 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1236 flags, &in->config);
1237 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1238 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1239 if (in->pcm != NULL) {
1240 pcm_close(in->pcm);
1241 in->pcm = NULL;
1242 }
1243 if (pcm_open_retry_count-- == 0) {
1244 ret = -EIO;
1245 goto error_open;
1246 }
1247 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1248 continue;
1249 }
1250 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001252
1253 ALOGV("%s: pcm_prepare", __func__);
1254 ret = pcm_prepare(in->pcm);
1255 if (ret < 0) {
1256 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1257 pcm_close(in->pcm);
1258 in->pcm = NULL;
1259 goto error_open;
1260 }
1261
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301262 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001263 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001264
Eric Laurentc8400632013-02-14 19:04:54 -08001265 return ret;
1266
1267error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301268 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001270error_config:
1271 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301272 /*
1273 * sleep 50ms to allow sufficient time for kernel
1274 * drivers to recover incases like SSR.
1275 */
1276 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001278
1279 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280}
1281
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001282void lock_input_stream(struct stream_in *in)
1283{
1284 pthread_mutex_lock(&in->pre_lock);
1285 pthread_mutex_lock(&in->lock);
1286 pthread_mutex_unlock(&in->pre_lock);
1287}
1288
1289void lock_output_stream(struct stream_out *out)
1290{
1291 pthread_mutex_lock(&out->pre_lock);
1292 pthread_mutex_lock(&out->lock);
1293 pthread_mutex_unlock(&out->pre_lock);
1294}
1295
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001296/* must be called with out->lock locked */
1297static int send_offload_cmd_l(struct stream_out* out, int command)
1298{
1299 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1300
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001301 if (!cmd) {
1302 ALOGE("failed to allocate mem for command 0x%x", command);
1303 return -ENOMEM;
1304 }
1305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 ALOGVV("%s %d", __func__, command);
1307
1308 cmd->cmd = command;
1309 list_add_tail(&out->offload_cmd_list, &cmd->node);
1310 pthread_cond_signal(&out->offload_cond);
1311 return 0;
1312}
1313
1314/* must be called iwth out->lock locked */
1315static void stop_compressed_output_l(struct stream_out *out)
1316{
1317 out->offload_state = OFFLOAD_STATE_IDLE;
1318 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001319 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 if (out->compr != NULL) {
1321 compress_stop(out->compr);
1322 while (out->offload_thread_blocked) {
1323 pthread_cond_wait(&out->cond, &out->lock);
1324 }
1325 }
1326}
1327
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001328bool is_offload_usecase(audio_usecase_t uc_id)
1329{
1330 unsigned int i;
1331 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1332 if (uc_id == offload_usecases[i])
1333 return true;
1334 }
1335 return false;
1336}
1337
vivek mehta446c3962015-09-14 10:57:35 -07001338static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001339{
vivek mehta446c3962015-09-14 10:57:35 -07001340 audio_usecase_t ret_uc = USECASE_INVALID;
1341 unsigned int offload_uc_index;
1342 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1343 if (!adev->multi_offload_enable) {
1344 if (is_direct_pcm)
1345 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1346 else
1347 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001348
vivek mehta446c3962015-09-14 10:57:35 -07001349 pthread_mutex_lock(&adev->lock);
1350 if (get_usecase_from_list(adev, ret_uc) != NULL)
1351 ret_uc = USECASE_INVALID;
1352 pthread_mutex_unlock(&adev->lock);
1353
1354 return ret_uc;
1355 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001356
1357 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001358 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1359 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1360 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1361 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001362 break;
1363 }
1364 }
vivek mehta446c3962015-09-14 10:57:35 -07001365
1366 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1367 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001368}
1369
1370static void free_offload_usecase(struct audio_device *adev,
1371 audio_usecase_t uc_id)
1372{
vivek mehta446c3962015-09-14 10:57:35 -07001373 unsigned int offload_uc_index;
1374 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1375
1376 if (!adev->multi_offload_enable)
1377 return;
1378
1379 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1380 if (offload_usecases[offload_uc_index] == uc_id) {
1381 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001382 break;
1383 }
1384 }
1385 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1386}
1387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001388static void *offload_thread_loop(void *context)
1389{
1390 struct stream_out *out = (struct stream_out *) context;
1391 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001392 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001394 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1395 set_sched_policy(0, SP_FOREGROUND);
1396 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1397
1398 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400 for (;;) {
1401 struct offload_cmd *cmd = NULL;
1402 stream_callback_event_t event;
1403 bool send_callback = false;
1404
1405 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1406 __func__, list_empty(&out->offload_cmd_list),
1407 out->offload_state);
1408 if (list_empty(&out->offload_cmd_list)) {
1409 ALOGV("%s SLEEPING", __func__);
1410 pthread_cond_wait(&out->offload_cond, &out->lock);
1411 ALOGV("%s RUNNING", __func__);
1412 continue;
1413 }
1414
1415 item = list_head(&out->offload_cmd_list);
1416 cmd = node_to_item(item, struct offload_cmd, node);
1417 list_remove(item);
1418
1419 ALOGVV("%s STATE %d CMD %d out->compr %p",
1420 __func__, out->offload_state, cmd->cmd, out->compr);
1421
1422 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1423 free(cmd);
1424 break;
1425 }
1426
1427 if (out->compr == NULL) {
1428 ALOGE("%s: Compress handle is NULL", __func__);
1429 pthread_cond_signal(&out->cond);
1430 continue;
1431 }
1432 out->offload_thread_blocked = true;
1433 pthread_mutex_unlock(&out->lock);
1434 send_callback = false;
1435 switch(cmd->cmd) {
1436 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001437 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001438 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001439 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001440 send_callback = true;
1441 event = STREAM_CBK_EVENT_WRITE_READY;
1442 break;
1443 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001444 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301445 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001446 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301447 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001448 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301449 if (ret < 0)
1450 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301451 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301452 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001453 compress_drain(out->compr);
1454 else
1455 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301456 if (ret != -ENETRESET) {
1457 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301458 pthread_mutex_lock(&out->lock);
1459 out->send_new_metadata = 1;
1460 out->send_next_track_params = true;
1461 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301462 event = STREAM_CBK_EVENT_DRAIN_READY;
1463 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1464 } else
1465 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001466 break;
1467 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001468 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001469 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001470 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001471 send_callback = true;
1472 event = STREAM_CBK_EVENT_DRAIN_READY;
1473 break;
1474 default:
1475 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1476 break;
1477 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001478 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001479 out->offload_thread_blocked = false;
1480 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001481 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001482 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001484 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001485 free(cmd);
1486 }
1487
1488 pthread_cond_signal(&out->cond);
1489 while (!list_empty(&out->offload_cmd_list)) {
1490 item = list_head(&out->offload_cmd_list);
1491 list_remove(item);
1492 free(node_to_item(item, struct offload_cmd, node));
1493 }
1494 pthread_mutex_unlock(&out->lock);
1495
1496 return NULL;
1497}
1498
1499static int create_offload_callback_thread(struct stream_out *out)
1500{
1501 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1502 list_init(&out->offload_cmd_list);
1503 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1504 offload_thread_loop, out);
1505 return 0;
1506}
1507
1508static int destroy_offload_callback_thread(struct stream_out *out)
1509{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001510 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001511 stop_compressed_output_l(out);
1512 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1513
1514 pthread_mutex_unlock(&out->lock);
1515 pthread_join(out->offload_thread, (void **) NULL);
1516 pthread_cond_destroy(&out->offload_cond);
1517
1518 return 0;
1519}
1520
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521static bool allow_hdmi_channel_config(struct audio_device *adev)
1522{
1523 struct listnode *node;
1524 struct audio_usecase *usecase;
1525 bool ret = true;
1526
1527 list_for_each(node, &adev->usecase_list) {
1528 usecase = node_to_item(node, struct audio_usecase, list);
1529 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1530 /*
1531 * If voice call is already existing, do not proceed further to avoid
1532 * disabling/enabling both RX and TX devices, CSD calls, etc.
1533 * Once the voice call done, the HDMI channels can be configured to
1534 * max channels of remaining use cases.
1535 */
1536 if (usecase->id == USECASE_VOICE_CALL) {
1537 ALOGD("%s: voice call is active, no change in HDMI channels",
1538 __func__);
1539 ret = false;
1540 break;
1541 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1542 ALOGD("%s: multi channel playback is active, "
1543 "no change in HDMI channels", __func__);
1544 ret = false;
1545 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001546 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001547 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001548 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1549 ", no change in HDMI channels", __func__,
1550 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001551 ret = false;
1552 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001553 }
1554 }
1555 }
1556 return ret;
1557}
1558
1559static int check_and_set_hdmi_channels(struct audio_device *adev,
1560 unsigned int channels)
1561{
1562 struct listnode *node;
1563 struct audio_usecase *usecase;
1564
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001565 unsigned int supported_channels = platform_edid_get_max_channels(
1566 adev->platform);
1567 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001568 /* Check if change in HDMI channel config is allowed */
1569 if (!allow_hdmi_channel_config(adev))
1570 return 0;
1571
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001572 if (channels > supported_channels)
1573 channels = supported_channels;
1574
Eric Laurent07eeafd2013-10-06 12:52:49 -07001575 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001576 ALOGD("%s: Requested channels are same as current channels(%d)",
1577 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001578 return 0;
1579 }
1580
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001581 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001583 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001584 adev->cur_hdmi_channels = channels;
1585
1586 /*
1587 * Deroute all the playback streams routed to HDMI so that
1588 * the back end is deactivated. Note that backend will not
1589 * be deactivated if any one stream is connected to it.
1590 */
1591 list_for_each(node, &adev->usecase_list) {
1592 usecase = node_to_item(node, struct audio_usecase, list);
1593 if (usecase->type == PCM_PLAYBACK &&
1594 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001595 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001596 }
1597 }
1598
1599 /*
1600 * Enable all the streams disabled above. Now the HDMI backend
1601 * will be activated with new channel configuration
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 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001608 }
1609 }
1610
1611 return 0;
1612}
1613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614static int stop_output_stream(struct stream_out *out)
1615{
1616 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 struct audio_usecase *uc_info;
1618 struct audio_device *adev = out->dev;
1619
Eric Laurent994a6932013-07-17 11:51:42 -07001620 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 uc_info = get_usecase_from_list(adev, out->usecase);
1623 if (uc_info == NULL) {
1624 ALOGE("%s: Could not find the usecase (%d) in the list",
1625 __func__, out->usecase);
1626 return -EINVAL;
1627 }
1628
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001629 if (is_offload_usecase(out->usecase) &&
1630 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001631 if (adev->visualizer_stop_output != NULL)
1632 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001633
1634 audio_extn_dts_remove_state_notifier_node(out->usecase);
1635
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001636 if (adev->offload_effects_stop_output != NULL)
1637 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1638 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001639
Eric Laurent150dbfe2013-02-27 14:31:02 -08001640 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001641 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642
1643 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001644 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001646 list_remove(&uc_info->list);
1647 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001649 if (is_offload_usecase(out->usecase) &&
1650 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1651 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1652 ALOGV("Disable passthrough , reset mixer to pcm");
1653 /* NO_PASSTHROUGH */
1654 out->compr_config.codec->compr_passthr = 0;
1655 audio_extn_dolby_set_hdmi_config(adev, out);
1656 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1657 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001658 /* Must be called after removing the usecase from list */
1659 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1660 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1661
Eric Laurent994a6932013-07-17 11:51:42 -07001662 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 return ret;
1664}
1665
1666int start_output_stream(struct stream_out *out)
1667{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001669 int sink_channels = 0;
1670 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 struct audio_usecase *uc_info;
1672 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301673 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001675 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1676 ret = -EINVAL;
1677 goto error_config;
1678 }
1679
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301680 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1681 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1682 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301683
Naresh Tanniru80659832014-06-04 18:17:56 +05301684 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301685 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301686 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687 goto error_config;
1688 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301689
Eric Laurentb23d5282013-05-14 15:27:20 -07001690 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 if (out->pcm_device_id < 0) {
1692 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1693 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001694 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001695 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 }
1697
1698 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001699
1700 if (!uc_info) {
1701 ret = -ENOMEM;
1702 goto error_config;
1703 }
1704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 uc_info->id = out->usecase;
1706 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001707 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708 uc_info->devices = out->devices;
1709 uc_info->in_snd_device = SND_DEVICE_NONE;
1710 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001711 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001712 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001713 if (is_offload_usecase(out->usecase)) {
1714 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001715 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1716 }
1717 }
Mingming Yin9c041392014-05-01 15:37:31 -07001718 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1719 if (!strncmp("true", prop_value, 4)) {
1720 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001721 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1722 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001723 check_and_set_hdmi_channels(adev, sink_channels);
1724 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001725 if (is_offload_usecase(out->usecase)) {
1726 unsigned int ch_count = out->compr_config.codec->ch_in;
1727 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1728 /* backend channel config for passthrough stream is stereo */
1729 ch_count = 2;
1730 check_and_set_hdmi_channels(adev, ch_count);
1731 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001732 check_and_set_hdmi_channels(adev, out->config.channels);
1733 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001734 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001735 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001736 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301738 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1739 adev->perf_lock_opts,
1740 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 select_devices(adev, out->usecase);
1742
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001743 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1744 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001745 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001746 unsigned int flags = PCM_OUT;
1747 unsigned int pcm_open_retry_count = 0;
1748 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1749 flags |= PCM_MMAP | PCM_NOIRQ;
1750 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1751 } else
1752 flags |= PCM_MONOTONIC;
1753
1754 while (1) {
1755 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1756 flags, &out->config);
1757 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1758 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1759 if (out->pcm != NULL) {
1760 pcm_close(out->pcm);
1761 out->pcm = NULL;
1762 }
1763 if (pcm_open_retry_count-- == 0) {
1764 ret = -EIO;
1765 goto error_open;
1766 }
1767 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1768 continue;
1769 }
1770 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001772
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001773 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1774 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001775
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001776 ALOGV("%s: pcm_prepare", __func__);
1777 if (pcm_is_ready(out->pcm)) {
1778 ret = pcm_prepare(out->pcm);
1779 if (ret < 0) {
1780 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1781 pcm_close(out->pcm);
1782 out->pcm = NULL;
1783 goto error_open;
1784 }
1785 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001787 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1788 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001790 out->compr = compress_open(adev->snd_card,
1791 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 COMPRESS_IN, &out->compr_config);
1793 if (out->compr && !is_compress_ready(out->compr)) {
1794 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1795 compress_close(out->compr);
1796 out->compr = NULL;
1797 ret = -EIO;
1798 goto error_open;
1799 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301800 /* compress_open sends params of the track, so reset the flag here */
1801 out->is_compr_metadata_avail = false;
1802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 if (out->offload_callback)
1804 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001805
Fred Oh3f43e742015-03-04 18:42:34 -08001806 /* Since small bufs uses blocking writes, a write will be blocked
1807 for the default max poll time (20s) in the event of an SSR.
1808 Reduce the poll time to observe and deal with SSR faster.
1809 */
1810 if (out->use_small_bufs) {
1811 compress_set_max_poll_wait(out->compr, 1000);
1812 }
1813
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001814 audio_extn_dts_create_state_notifier_node(out->usecase);
1815 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1816 popcount(out->channel_mask),
1817 out->playback_started);
1818
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001819#ifdef DS1_DOLBY_DDP_ENABLED
1820 if (audio_extn_is_dolby_format(out->format))
1821 audio_extn_dolby_send_ddp_endp_params(adev);
1822#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001823 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1824 if (adev->visualizer_start_output != NULL)
1825 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1826 if (adev->offload_effects_start_output != NULL)
1827 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001828 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301831 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001832 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301836 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001838error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301839 /*
1840 * sleep 50ms to allow sufficient time for kernel
1841 * drivers to recover incases like SSR.
1842 */
1843 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001844 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845}
1846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847static int check_input_parameters(uint32_t sample_rate,
1848 audio_format_t format,
1849 int channel_count)
1850{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001851 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001853 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001854 !voice_extn_compress_voip_is_format_supported(format) &&
1855 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001856
1857 switch (channel_count) {
1858 case 1:
1859 case 2:
1860 case 6:
1861 break;
1862 default:
1863 ret = -EINVAL;
1864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865
1866 switch (sample_rate) {
1867 case 8000:
1868 case 11025:
1869 case 12000:
1870 case 16000:
1871 case 22050:
1872 case 24000:
1873 case 32000:
1874 case 44100:
1875 case 48000:
1876 break;
1877 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001878 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 }
1880
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001881 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882}
1883
1884static size_t get_input_buffer_size(uint32_t sample_rate,
1885 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001886 int channel_count,
1887 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888{
1889 size_t size = 0;
1890
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001891 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1892 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001894 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001895 if (is_low_latency)
1896 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001897 /* ToDo: should use frame_size computed based on the format and
1898 channel_count here. */
1899 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001901 /* make sure the size is multiple of 32 bytes
1902 * At 48 kHz mono 16-bit PCM:
1903 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1904 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1905 */
1906 size += 0x1f;
1907 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001908
1909 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910}
1911
1912static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1913{
1914 struct stream_out *out = (struct stream_out *)stream;
1915
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001916 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917}
1918
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001919static int out_set_sample_rate(struct audio_stream *stream __unused,
1920 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921{
1922 return -ENOSYS;
1923}
1924
1925static size_t out_get_buffer_size(const struct audio_stream *stream)
1926{
1927 struct stream_out *out = (struct stream_out *)stream;
1928
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001929 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001931 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1932 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001934 return out->config.period_size *
1935 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936}
1937
1938static uint32_t out_get_channels(const struct audio_stream *stream)
1939{
1940 struct stream_out *out = (struct stream_out *)stream;
1941
1942 return out->channel_mask;
1943}
1944
1945static audio_format_t out_get_format(const struct audio_stream *stream)
1946{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001947 struct stream_out *out = (struct stream_out *)stream;
1948
1949 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950}
1951
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001952static int out_set_format(struct audio_stream *stream __unused,
1953 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954{
1955 return -ENOSYS;
1956}
1957
1958static int out_standby(struct audio_stream *stream)
1959{
1960 struct stream_out *out = (struct stream_out *)stream;
1961 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001962
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301963 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1964 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001965 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1966 /* Ignore standby in case of voip call because the voip output
1967 * stream is closed in adev_close_output_stream()
1968 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301969 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001970 return 0;
1971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001973 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001975 if (adev->adm_deregister_stream)
1976 adev->adm_deregister_stream(adev->adm_data, out->handle);
1977
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001978 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001980 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001981 if (out->pcm) {
1982 pcm_close(out->pcm);
1983 out->pcm = NULL;
1984 }
1985 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001986 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001987 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301988 out->send_next_track_params = false;
1989 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001990 out->gapless_mdata.encoder_delay = 0;
1991 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 if (out->compr != NULL) {
1993 compress_close(out->compr);
1994 out->compr = NULL;
1995 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001998 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 }
2000 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302001 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 return 0;
2003}
2004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002005static int out_dump(const struct audio_stream *stream __unused,
2006 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007{
2008 return 0;
2009}
2010
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002011static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2012{
2013 int ret = 0;
2014 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002015
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002016 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002017 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002018 return -EINVAL;
2019 }
2020
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302021 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002022
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002023 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2024 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302025 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002026 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2028 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302029 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 }
2031
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002032 ALOGV("%s new encoder delay %u and padding %u", __func__,
2033 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2034
2035 return 0;
2036}
2037
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002038static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2039{
2040 return out == adev->primary_output || out == adev->voice_tx_output;
2041}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2044{
2045 struct stream_out *out = (struct stream_out *)stream;
2046 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002047 struct audio_usecase *usecase;
2048 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 struct str_parms *parms;
2050 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002051 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002052 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
sangwoobc677242013-08-08 16:53:43 +09002054 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002055 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302057 if (!parms)
2058 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002059 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2060 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002062 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002063 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002065 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302066 * When HDMI cable is unplugged/usb hs is disconnected the
2067 * music playback is paused and the policy manager sends routing=0
2068 * But the audioflingercontinues to write data until standby time
2069 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002070 * Avoid this by routing audio to speaker until standby.
2071 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302072 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2073 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002074 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002075 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2076 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077 }
2078
2079 /*
2080 * select_devices() call below switches all the usecases on the same
2081 * backend to the new device. Refer to check_usecases_codec_backend() in
2082 * the select_devices(). But how do we undo this?
2083 *
2084 * For example, music playback is active on headset (deep-buffer usecase)
2085 * and if we go to ringtones and select a ringtone, low-latency usecase
2086 * will be started on headset+speaker. As we can't enable headset+speaker
2087 * and headset devices at the same time, select_devices() switches the music
2088 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2089 * So when the ringtone playback is completed, how do we undo the same?
2090 *
2091 * We are relying on the out_set_parameters() call on deep-buffer output,
2092 * once the ringtone playback is ended.
2093 * NOTE: We should not check if the current devices are same as new devices.
2094 * Because select_devices() must be called to switch back the music
2095 * playback to headset.
2096 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002097 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002098 out->devices = val;
2099
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302100 if (!out->standby) {
2101 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2102 adev->perf_lock_opts,
2103 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302105 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2106 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002107
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002108 if (output_drives_call(adev, out)) {
2109 if(!voice_is_in_call(adev)) {
2110 if (adev->mode == AUDIO_MODE_IN_CALL) {
2111 adev->current_call_output = out;
2112 ret = voice_start_call(adev);
2113 }
2114 } else {
2115 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002116 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002117 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002118 }
2119 }
2120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002122 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002124
2125 if (out == adev->primary_output) {
2126 pthread_mutex_lock(&adev->lock);
2127 audio_extn_set_parameters(adev, parms);
2128 pthread_mutex_unlock(&adev->lock);
2129 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002130 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002131 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002132 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002133
2134 audio_extn_dts_create_state_notifier_node(out->usecase);
2135 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2136 popcount(out->channel_mask),
2137 out->playback_started);
2138
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002139 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002140 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302143error:
Eric Laurent994a6932013-07-17 11:51:42 -07002144 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 return ret;
2146}
2147
2148static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2149{
2150 struct stream_out *out = (struct stream_out *)stream;
2151 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002152 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 char value[256];
2154 struct str_parms *reply = str_parms_create();
2155 size_t i, j;
2156 int ret;
2157 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002158
2159 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002160 if (reply) {
2161 str_parms_destroy(reply);
2162 }
2163 if (query) {
2164 str_parms_destroy(query);
2165 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002166 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2167 return NULL;
2168 }
2169
Eric Laurent994a6932013-07-17 11:51:42 -07002170 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2172 if (ret >= 0) {
2173 value[0] = '\0';
2174 i = 0;
2175 while (out->supported_channel_masks[i] != 0) {
2176 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2177 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2178 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002179 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002181 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 first = false;
2183 break;
2184 }
2185 }
2186 i++;
2187 }
2188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2189 str = str_parms_to_str(reply);
2190 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002191 voice_extn_out_get_parameters(out, query, reply);
2192 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002193 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002194 free(str);
2195 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002198
Alexy Joseph62142aa2015-11-16 15:10:34 -08002199
2200 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2201 if (ret >= 0) {
2202 value[0] = '\0';
2203 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2204 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302205 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002206 } else {
2207 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302208 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002209 }
2210 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002211 if (str)
2212 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002213 str = str_parms_to_str(reply);
2214 }
2215
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002216 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2217 if (ret >= 0) {
2218 value[0] = '\0';
2219 i = 0;
2220 first = true;
2221 while (out->supported_formats[i] != 0) {
2222 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2223 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2224 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002225 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002226 }
2227 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2228 first = false;
2229 break;
2230 }
2231 }
2232 i++;
2233 }
2234 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002235 if (str)
2236 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002237 str = str_parms_to_str(reply);
2238 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 str_parms_destroy(query);
2240 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002241 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 return str;
2243}
2244
2245static uint32_t out_get_latency(const struct audio_stream_out *stream)
2246{
2247 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002248 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Alexy Josephaa54c872014-12-03 02:46:47 -08002250 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002251 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002252 } else {
2253 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002255 }
2256
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302257 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002258 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259}
2260
2261static int out_set_volume(struct audio_stream_out *stream, float left,
2262 float right)
2263{
Eric Laurenta9024de2013-04-04 09:19:12 -07002264 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 int volume[2];
2266
Eric Laurenta9024de2013-04-04 09:19:12 -07002267 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2268 /* only take left channel into account: the API is for stereo anyway */
2269 out->muted = (left == 0.0f);
2270 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002271 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002272 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2273 /*
2274 * Set mute or umute on HDMI passthrough stream.
2275 * Only take left channel into account.
2276 * Mute is 0 and unmute 1
2277 */
2278 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2279 } else {
2280 char mixer_ctl_name[128];
2281 struct audio_device *adev = out->dev;
2282 struct mixer_ctl *ctl;
2283 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002284 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002285
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002286 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2287 "Compress Playback %d Volume", pcm_device_id);
2288 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2289 if (!ctl) {
2290 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2291 __func__, mixer_ctl_name);
2292 return -EINVAL;
2293 }
2294 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2295 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2296 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2297 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002299 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301 return -ENOSYS;
2302}
2303
2304static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2305 size_t bytes)
2306{
2307 struct stream_out *out = (struct stream_out *)stream;
2308 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302309 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002310 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002312 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302313
Naresh Tanniru80659832014-06-04 18:17:56 +05302314 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002315
Ashish Jainbbce4322016-02-16 13:25:27 +05302316 if (is_offload_usecase(out->usecase)) {
2317 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302318 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2319 pthread_mutex_unlock(&out->lock);
2320 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302321 } else {
2322 /* increase written size during SSR to avoid mismatch
2323 * with the written frames count in AF
2324 */
2325 out->written += bytes / (out->config.channels * sizeof(short));
2326 ALOGD(" %s: sound card is not active/SSR state", __func__);
2327 ret= -EIO;
2328 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302329 }
2330 }
2331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002333 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002334 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002335 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2336 ret = voice_extn_compress_voip_start_output_stream(out);
2337 else
2338 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002339 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002342 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 goto exit;
2344 }
vivek mehta446c3962015-09-14 10:57:35 -07002345 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002346 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348
Ashish Jain81eb2a82015-05-13 10:52:34 +05302349 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2350 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2351 adev->is_channel_status_set = true;
2352 }
2353
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002354 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002355 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002356 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002357 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002358 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2359 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302360 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2361 ALOGD("copl(%p):send next track params in gapless", out);
2362 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2363 out->send_next_track_params = false;
2364 out->is_compr_metadata_avail = false;
2365 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002366 }
2367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302369 if (ret < 0)
2370 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002371 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002372 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302373 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302375 } else if (-ENETRESET == ret) {
2376 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2377 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2378 pthread_mutex_unlock(&out->lock);
2379 out_standby(&out->stream.common);
2380 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302382 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002384 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 out->playback_started = 1;
2386 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002387
2388 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2389 popcount(out->channel_mask),
2390 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 }
2392 pthread_mutex_unlock(&out->lock);
2393 return ret;
2394 } else {
2395 if (out->pcm) {
2396 if (out->muted)
2397 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002400
2401 if (adev->adm_request_focus)
2402 adev->adm_request_focus(adev->adm_data, out->handle);
2403
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002404 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2405 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2406 else
2407 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002408
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302409 if (ret < 0)
2410 ret = -errno;
2411 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002412 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002413
2414 if (adev->adm_abandon_focus)
2415 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417 }
2418
2419exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302420 /* ToDo: There may be a corner case when SSR happens back to back during
2421 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302422 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302423 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302424 }
2425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 pthread_mutex_unlock(&out->lock);
2427
2428 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002429 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002430 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302431 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302432 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302433 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302434 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302435 out->standby = true;
2436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302438 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302439 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 }
2441 return bytes;
2442}
2443
2444static int out_get_render_position(const struct audio_stream_out *stream,
2445 uint32_t *dsp_frames)
2446{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302448 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002449
2450 if (dsp_frames == NULL)
2451 return -EINVAL;
2452
2453 *dsp_frames = 0;
2454 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002455 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002456 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302458 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302460 if (ret < 0)
2461 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 ALOGVV("%s rendered frames %d sample_rate %d",
2463 __func__, *dsp_frames, out->sample_rate);
2464 }
2465 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302466 if (-ENETRESET == ret) {
2467 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2468 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2469 return -EINVAL;
2470 } else if(ret < 0) {
2471 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2472 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302473 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2474 /*
2475 * Handle corner case where compress session is closed during SSR
2476 * and timestamp is queried
2477 */
2478 ALOGE(" ERROR: sound card not active, return error");
2479 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302480 } else {
2481 return 0;
2482 }
Zhou Song32a556e2015-05-05 10:46:56 +08002483 } else if (audio_is_linear_pcm(out->format)) {
2484 *dsp_frames = out->written;
2485 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 } else
2487 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488}
2489
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002490static int out_add_audio_effect(const struct audio_stream *stream __unused,
2491 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492{
2493 return 0;
2494}
2495
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002496static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2497 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498{
2499 return 0;
2500}
2501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002502static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2503 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504{
2505 return -EINVAL;
2506}
2507
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002508static int out_get_presentation_position(const struct audio_stream_out *stream,
2509 uint64_t *frames, struct timespec *timestamp)
2510{
2511 struct stream_out *out = (struct stream_out *)stream;
2512 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002513 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002514
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002515 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002516
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002517 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002518 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302519 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002520 &out->sample_rate);
2521 ALOGVV("%s rendered frames %ld sample_rate %d",
2522 __func__, dsp_frames, out->sample_rate);
2523 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302524 if (ret < 0)
2525 ret = -errno;
2526 if (-ENETRESET == ret) {
2527 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2528 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2529 ret = -EINVAL;
2530 } else
2531 ret = 0;
2532
Eric Laurent949a0892013-09-20 09:20:13 -07002533 /* this is the best we can do */
2534 clock_gettime(CLOCK_MONOTONIC, timestamp);
2535 }
2536 } else {
2537 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002538 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002539 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2540 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002541 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002542 // This adjustment accounts for buffering after app processor.
2543 // It is based on estimated DSP latency per use case, rather than exact.
2544 signed_frames -=
2545 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2546
Eric Laurent949a0892013-09-20 09:20:13 -07002547 // It would be unusual for this value to be negative, but check just in case ...
2548 if (signed_frames >= 0) {
2549 *frames = signed_frames;
2550 ret = 0;
2551 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002552 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302553 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2554 *frames = out->written;
2555 clock_gettime(CLOCK_MONOTONIC, timestamp);
2556 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002557 }
2558 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002559 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002560 return ret;
2561}
2562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563static int out_set_callback(struct audio_stream_out *stream,
2564 stream_callback_t callback, void *cookie)
2565{
2566 struct stream_out *out = (struct stream_out *)stream;
2567
2568 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002569 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002570 out->offload_callback = callback;
2571 out->offload_cookie = cookie;
2572 pthread_mutex_unlock(&out->lock);
2573 return 0;
2574}
2575
2576static int out_pause(struct audio_stream_out* stream)
2577{
2578 struct stream_out *out = (struct stream_out *)stream;
2579 int status = -ENOSYS;
2580 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002581 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002582 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002583 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302585 struct audio_device *adev = out->dev;
2586 int snd_scard_state = get_snd_card_state(adev);
2587
2588 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2589 status = compress_pause(out->compr);
2590
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002591 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002592
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302593 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002594 audio_extn_dts_notify_playback_state(out->usecase, 0,
2595 out->sample_rate, popcount(out->channel_mask),
2596 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 }
2598 pthread_mutex_unlock(&out->lock);
2599 }
2600 return status;
2601}
2602
2603static int out_resume(struct audio_stream_out* stream)
2604{
2605 struct stream_out *out = (struct stream_out *)stream;
2606 int status = -ENOSYS;
2607 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002608 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002609 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002611 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302613 struct audio_device *adev = out->dev;
2614 int snd_scard_state = get_snd_card_state(adev);
2615
2616 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2617 status = compress_resume(out->compr);
2618
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002619 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002620
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302621 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002622 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2623 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 }
2625 pthread_mutex_unlock(&out->lock);
2626 }
2627 return status;
2628}
2629
2630static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2631{
2632 struct stream_out *out = (struct stream_out *)stream;
2633 int status = -ENOSYS;
2634 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002635 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002636 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002637 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2638 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2639 else
2640 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2641 pthread_mutex_unlock(&out->lock);
2642 }
2643 return status;
2644}
2645
2646static int out_flush(struct audio_stream_out* stream)
2647{
2648 struct stream_out *out = (struct stream_out *)stream;
2649 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002650 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002651 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002652 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002653 stop_compressed_output_l(out);
2654 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002655 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 return 0;
2657 }
2658 return -ENOSYS;
2659}
2660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661/** audio_stream_in implementation **/
2662static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2663{
2664 struct stream_in *in = (struct stream_in *)stream;
2665
2666 return in->config.rate;
2667}
2668
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002669static int in_set_sample_rate(struct audio_stream *stream __unused,
2670 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671{
2672 return -ENOSYS;
2673}
2674
2675static size_t in_get_buffer_size(const struct audio_stream *stream)
2676{
2677 struct stream_in *in = (struct stream_in *)stream;
2678
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002679 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2680 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002681 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2682 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002683
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002684 return in->config.period_size *
2685 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686}
2687
2688static uint32_t in_get_channels(const struct audio_stream *stream)
2689{
2690 struct stream_in *in = (struct stream_in *)stream;
2691
2692 return in->channel_mask;
2693}
2694
2695static audio_format_t in_get_format(const struct audio_stream *stream)
2696{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002697 struct stream_in *in = (struct stream_in *)stream;
2698
2699 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700}
2701
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002702static int in_set_format(struct audio_stream *stream __unused,
2703 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
2705 return -ENOSYS;
2706}
2707
2708static int in_standby(struct audio_stream *stream)
2709{
2710 struct stream_in *in = (struct stream_in *)stream;
2711 struct audio_device *adev = in->dev;
2712 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302713 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2714 stream, in->usecase, use_case_table[in->usecase]);
2715
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002716 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2717 /* Ignore standby in case of voip call because the voip input
2718 * stream is closed in adev_close_input_stream()
2719 */
2720 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2721 return status;
2722 }
2723
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002724 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002725 if (!in->standby && in->is_st_session) {
2726 ALOGD("%s: sound trigger pcm stop lab", __func__);
2727 audio_extn_sound_trigger_stop_lab(in);
2728 in->standby = 1;
2729 }
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002732 if (adev->adm_deregister_stream)
2733 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2734
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002735 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002737 if (in->pcm) {
2738 pcm_close(in->pcm);
2739 in->pcm = NULL;
2740 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002742 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 }
2744 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002745 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 return status;
2747}
2748
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002749static int in_dump(const struct audio_stream *stream __unused,
2750 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751{
2752 return 0;
2753}
2754
2755static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2756{
2757 struct stream_in *in = (struct stream_in *)stream;
2758 struct audio_device *adev = in->dev;
2759 struct str_parms *parms;
2760 char *str;
2761 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002762 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302764 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 parms = str_parms_create_str(kvpairs);
2766
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302767 if (!parms)
2768 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002769 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002770 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002771
2772 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2773 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 val = atoi(value);
2775 /* no audio source uses val == 0 */
2776 if ((in->source != val) && (val != 0)) {
2777 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002778 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2779 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2780 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2781 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002782 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002783 err = voice_extn_compress_voip_open_input_stream(in);
2784 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002785 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002786 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002787 }
2788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 }
2790 }
2791
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002792 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2793 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002795 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 in->device = val;
2797 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002798 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002799 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 }
2801 }
2802
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002803done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002805 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806
2807 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302808error:
Eric Laurent994a6932013-07-17 11:51:42 -07002809 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 return ret;
2811}
2812
2813static char* in_get_parameters(const struct audio_stream *stream,
2814 const char *keys)
2815{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002816 struct stream_in *in = (struct stream_in *)stream;
2817 struct str_parms *query = str_parms_create_str(keys);
2818 char *str;
2819 char value[256];
2820 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002821
2822 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002823 if (reply) {
2824 str_parms_destroy(reply);
2825 }
2826 if (query) {
2827 str_parms_destroy(query);
2828 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002829 ALOGE("in_get_parameters: failed to create query or reply");
2830 return NULL;
2831 }
2832
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002833 ALOGV("%s: enter: keys - %s", __func__, keys);
2834
2835 voice_extn_in_get_parameters(in, query, reply);
2836
2837 str = str_parms_to_str(reply);
2838 str_parms_destroy(query);
2839 str_parms_destroy(reply);
2840
2841 ALOGV("%s: exit: returns - %s", __func__, str);
2842 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843}
2844
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002845static int in_set_gain(struct audio_stream_in *stream __unused,
2846 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847{
2848 return 0;
2849}
2850
2851static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2852 size_t bytes)
2853{
2854 struct stream_in *in = (struct stream_in *)stream;
2855 struct audio_device *adev = in->dev;
2856 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302857 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002859 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302860
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002861 if (in->is_st_session) {
2862 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2863 /* Read from sound trigger HAL */
2864 audio_extn_sound_trigger_read(in, buffer, bytes);
2865 pthread_mutex_unlock(&in->lock);
2866 return bytes;
2867 }
2868
Ashish Jainbbce4322016-02-16 13:25:27 +05302869 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002870 ALOGD(" %s: sound card is not active/SSR state", __func__);
2871 ret= -EIO;;
2872 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302873 }
2874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002876 pthread_mutex_lock(&adev->lock);
2877 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2878 ret = voice_extn_compress_voip_start_input_stream(in);
2879 else
2880 ret = start_input_stream(in);
2881 pthread_mutex_unlock(&adev->lock);
2882 if (ret != 0) {
2883 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 }
2885 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002886 if (adev->adm_register_input_stream)
2887 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002890 if (adev->adm_request_focus)
2891 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002894 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002895 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002896 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2897 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002898 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2899 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002900 else
2901 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302902 if (ret < 0)
2903 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 }
2905
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002906 if (adev->adm_abandon_focus)
2907 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 /*
2910 * Instead of writing zeroes here, we could trust the hardware
2911 * to always provide zeroes when muted.
2912 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302913 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2914 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 memset(buffer, 0, bytes);
2916
2917exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302918 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302919 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002920 if (-ENETRESET == ret)
2921 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 pthread_mutex_unlock(&in->lock);
2924
2925 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302926 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302927 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302928 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302929 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302930 in->standby = true;
2931 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302932 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002934 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302935 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302936 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 }
2938 return bytes;
2939}
2940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002941static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942{
2943 return 0;
2944}
2945
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002946static int add_remove_audio_effect(const struct audio_stream *stream,
2947 effect_handle_t effect,
2948 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002950 struct stream_in *in = (struct stream_in *)stream;
2951 int status = 0;
2952 effect_descriptor_t desc;
2953
2954 status = (*effect)->get_descriptor(effect, &desc);
2955 if (status != 0)
2956 return status;
2957
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002958 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002959 pthread_mutex_lock(&in->dev->lock);
2960 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2961 in->enable_aec != enable &&
2962 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2963 in->enable_aec = enable;
2964 if (!in->standby)
2965 select_devices(in->dev, in->usecase);
2966 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002967 if (in->enable_ns != enable &&
2968 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2969 in->enable_ns = enable;
2970 if (!in->standby)
2971 select_devices(in->dev, in->usecase);
2972 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002973 pthread_mutex_unlock(&in->dev->lock);
2974 pthread_mutex_unlock(&in->lock);
2975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 return 0;
2977}
2978
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002979static int in_add_audio_effect(const struct audio_stream *stream,
2980 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981{
Eric Laurent994a6932013-07-17 11:51:42 -07002982 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002983 return add_remove_audio_effect(stream, effect, true);
2984}
2985
2986static int in_remove_audio_effect(const struct audio_stream *stream,
2987 effect_handle_t effect)
2988{
Eric Laurent994a6932013-07-17 11:51:42 -07002989 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002990 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991}
2992
2993static int adev_open_output_stream(struct audio_hw_device *dev,
2994 audio_io_handle_t handle,
2995 audio_devices_t devices,
2996 audio_output_flags_t flags,
2997 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002998 struct audio_stream_out **stream_out,
2999 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000{
3001 struct audio_device *adev = (struct audio_device *)dev;
3002 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003003 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003004 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303007
3008 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3009 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003010 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303011 return -EINVAL;
3012 }
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3015
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303016 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3017 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3018 devices, flags, &out->stream);
3019
3020
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003021 if (!out) {
3022 return -ENOMEM;
3023 }
3024
Haynes Mathew George204045b2015-02-25 20:32:03 -08003025 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003026 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003027 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 if (devices == AUDIO_DEVICE_NONE)
3030 devices = AUDIO_DEVICE_OUT_SPEAKER;
3031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 out->flags = flags;
3033 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003034 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003035 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 out->sample_rate = config->sample_rate;
3037 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3038 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003039 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003040 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003041 out->non_blocking = 0;
3042 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
3044 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003045 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303046 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3047 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003048 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3049 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3050
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003051 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003052 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3053 ret = read_hdmi_channel_masks(out);
3054
3055 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3056 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003057 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003058 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003059 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003060
3061 if (config->sample_rate == 0)
3062 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3063 if (config->channel_mask == 0)
3064 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3065
3066 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3069 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003071 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3074 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003075 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003076 ret = voice_extn_compress_voip_open_output_stream(out);
3077 if (ret != 0) {
3078 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3079 __func__, ret);
3080 goto error_open;
3081 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003082 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3083 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3084
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3086 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3087 ALOGE("%s: Unsupported Offload information", __func__);
3088 ret = -EINVAL;
3089 goto error_open;
3090 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003091
3092 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3093 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3094 ALOGV("read and update_pass through formats");
3095 ret = audio_extn_dolby_update_passt_formats(adev, out);
3096 if(ret != 0) {
3097 goto error_open;
3098 }
3099 if(config->offload_info.format == 0)
3100 config->offload_info.format = out->supported_formats[0];
3101 }
3102
Mingming Yin90310102013-11-13 16:57:00 -08003103 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003104 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003105 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 ret = -EINVAL;
3107 goto error_open;
3108 }
3109
3110 out->compr_config.codec = (struct snd_codec *)
3111 calloc(1, sizeof(struct snd_codec));
3112
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003113 if (!out->compr_config.codec) {
3114 ret = -ENOMEM;
3115 goto error_open;
3116 }
3117
vivek mehta0ea887a2015-08-26 14:01:20 -07003118 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003119 out->usecase = get_offload_usecase(adev, true);
3120 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003121 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003122 out->stream.set_callback = out_set_callback;
3123 out->stream.pause = out_pause;
3124 out->stream.resume = out_resume;
3125 out->stream.drain = out_drain;
3126 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003127 out->usecase = get_offload_usecase(adev, false);
3128 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003129 }
vivek mehta446c3962015-09-14 10:57:35 -07003130
3131 if (out->usecase == USECASE_INVALID) {
3132 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3133 ret = -EEXIST;
3134 goto error_open;
3135 }
3136
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 if (config->offload_info.channel_mask)
3138 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003139 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003141 config->offload_info.channel_mask = config->channel_mask;
3142 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003143 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 out->sample_rate = config->offload_info.sample_rate;
3145
Mingming Yin3ee55c62014-08-04 14:23:35 -07003146 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003148 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003149 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003150 audio_extn_dolby_get_snd_codec_id(adev, out,
3151 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003152 else
3153 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003155
3156 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3157 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003158 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003159 platform_get_pcm_offload_buffer_size(&config->offload_info);
3160 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3161 out->compr_config.fragment_size =
3162 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003163 } else {
3164 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003165 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003166 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3168 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003169 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 out->compr_config.codec->bit_rate =
3171 config->offload_info.bit_rate;
3172 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003173 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303175 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003176 /*TODO: Do we need to change it for passthrough */
3177 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178
Manish Dewangana6fc5442015-08-24 20:30:31 +05303179 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3180 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3181 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3182 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003183 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3184 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003185 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003186 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003187 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3188 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003189
Mingming Yin3ee55c62014-08-04 14:23:35 -07003190 if (out->bit_width == 24) {
3191 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3192 }
3193
Amit Shekhar6f461b12014-08-01 14:52:58 -07003194 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303195 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3198 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003199
Mingming Yin497419f2015-07-01 16:57:32 -07003200 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003201 //this flag is set from framework only if its for PCM formats
3202 //no need to check for PCM format again
3203 out->non_blocking = 0;
3204 out->use_small_bufs = true;
3205 ALOGI("Keep write blocking for small buff: non_blockling %d",
3206 out->non_blocking);
3207 }
3208
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003209 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303210 out->send_next_track_params = false;
3211 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003212 out->offload_state = OFFLOAD_STATE_IDLE;
3213 out->playback_started = 0;
3214
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003215 audio_extn_dts_create_state_notifier_node(out->usecase);
3216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 create_offload_callback_thread(out);
3218 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3219 __func__, config->offload_info.version,
3220 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003221 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003222 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003223 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3224 ret = voice_check_and_set_incall_music_usecase(adev, out);
3225 if (ret != 0) {
3226 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3227 __func__, ret);
3228 goto error_open;
3229 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003230 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3231 if (config->sample_rate == 0)
3232 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3233 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3234 config->sample_rate != 8000) {
3235 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3236 ret = -EINVAL;
3237 goto error_open;
3238 }
3239 out->sample_rate = config->sample_rate;
3240 out->config.rate = config->sample_rate;
3241 if (config->format == AUDIO_FORMAT_DEFAULT)
3242 config->format = AUDIO_FORMAT_PCM_16_BIT;
3243 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3244 config->format = AUDIO_FORMAT_PCM_16_BIT;
3245 ret = -EINVAL;
3246 goto error_open;
3247 }
3248 out->format = config->format;
3249 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3250 out->config = pcm_config_afe_proxy_playback;
3251 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003252 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3253 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3254 out->config = pcm_config_low_latency;
3255 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003256 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003257 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3259 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003261 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3262 format = AUDIO_FORMAT_PCM_16_BIT;
3263 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3264 out->config = pcm_config_deep_buffer;
3265 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003266 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003267 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003268 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003269 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003270 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003271 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 }
3273
Amit Shekhar1d896042014-10-03 13:16:09 -07003274 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3275 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003276 /* TODO remove this hardcoding and check why width is zero*/
3277 if (out->bit_width == 0)
3278 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003279 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3280 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003281 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303282 out->bit_width, out->channel_mask,
3283 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003284 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3285 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3286 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003287 if(adev->primary_output == NULL)
3288 adev->primary_output = out;
3289 else {
3290 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003291 ret = -EEXIST;
3292 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003293 }
3294 }
3295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 /* Check if this usecase is already existing */
3297 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003298 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3299 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003302 ret = -EEXIST;
3303 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 }
3305 pthread_mutex_unlock(&adev->lock);
3306
3307 out->stream.common.get_sample_rate = out_get_sample_rate;
3308 out->stream.common.set_sample_rate = out_set_sample_rate;
3309 out->stream.common.get_buffer_size = out_get_buffer_size;
3310 out->stream.common.get_channels = out_get_channels;
3311 out->stream.common.get_format = out_get_format;
3312 out->stream.common.set_format = out_set_format;
3313 out->stream.common.standby = out_standby;
3314 out->stream.common.dump = out_dump;
3315 out->stream.common.set_parameters = out_set_parameters;
3316 out->stream.common.get_parameters = out_get_parameters;
3317 out->stream.common.add_audio_effect = out_add_audio_effect;
3318 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3319 out->stream.get_latency = out_get_latency;
3320 out->stream.set_volume = out_set_volume;
3321 out->stream.write = out_write;
3322 out->stream.get_render_position = out_get_render_position;
3323 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003324 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003327 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003328 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
3330 config->format = out->stream.common.get_format(&out->stream.common);
3331 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3332 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3333
3334 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303335 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003336 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003337
3338 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3339 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3340 popcount(out->channel_mask), out->playback_started);
3341
Eric Laurent994a6932013-07-17 11:51:42 -07003342 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003344
3345error_open:
3346 free(out);
3347 *stream_out = NULL;
3348 ALOGD("%s: exit: ret %d", __func__, ret);
3349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350}
3351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003352static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 struct audio_stream_out *stream)
3354{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 struct stream_out *out = (struct stream_out *)stream;
3356 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003357 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303359 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3360
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303362 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003363 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303364 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003365 if(ret != 0)
3366 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3367 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003368 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003369 out_standby(&stream->common);
3370
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003371 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003372 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003374 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 if (out->compr_config.codec != NULL)
3376 free(out->compr_config.codec);
3377 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003378
3379 if (adev->voice_tx_output == out)
3380 adev->voice_tx_output = NULL;
3381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 pthread_cond_destroy(&out->cond);
3383 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003385 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386}
3387
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003388static void close_compress_sessions(struct audio_device *adev)
3389{
Mingming Yin7b762e72015-03-04 13:47:32 -08003390 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303391 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003392 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003393 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303394
3395 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003396 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303397 if (is_offload_usecase(usecase->id)) {
3398 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003399 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3400 out = usecase->stream.out;
3401 pthread_mutex_unlock(&adev->lock);
3402 out_standby(&out->stream.common);
3403 pthread_mutex_lock(&adev->lock);
3404 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303405 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003406 }
3407 pthread_mutex_unlock(&adev->lock);
3408}
3409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3411{
3412 struct audio_device *adev = (struct audio_device *)dev;
3413 struct str_parms *parms;
3414 char *str;
3415 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003416 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003417 int ret;
3418 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003420 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303423 if (!parms)
3424 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003425 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3426 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303427 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303428 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303429 struct listnode *node;
3430 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303431 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303432 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303433 } else if (strstr(snd_card_status, "ONLINE")) {
3434 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303435 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003436 //send dts hpx license if enabled
3437 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303438 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303439 }
3440
3441 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003442 status = voice_set_parameters(adev, parms);
3443 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003444 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003446 status = platform_set_parameters(adev->platform, parms);
3447 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003448 goto done;
3449
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003450 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3451 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003452 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3454 adev->bluetooth_nrec = true;
3455 else
3456 adev->bluetooth_nrec = false;
3457 }
3458
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003459 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3460 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3462 adev->screen_off = false;
3463 else
3464 adev->screen_off = true;
3465 }
3466
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003467 ret = str_parms_get_int(parms, "rotation", &val);
3468 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003469 bool reverse_speakers = false;
3470 switch(val) {
3471 // FIXME: note that the code below assumes that the speakers are in the correct placement
3472 // relative to the user when the device is rotated 90deg from its default rotation. This
3473 // assumption is device-specific, not platform-specific like this code.
3474 case 270:
3475 reverse_speakers = true;
3476 break;
3477 case 0:
3478 case 90:
3479 case 180:
3480 break;
3481 default:
3482 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003483 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003484 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003485 if (status == 0) {
3486 if (adev->speaker_lr_swap != reverse_speakers) {
3487 adev->speaker_lr_swap = reverse_speakers;
3488 // only update the selected device if there is active pcm playback
3489 struct audio_usecase *usecase;
3490 struct listnode *node;
3491 list_for_each(node, &adev->usecase_list) {
3492 usecase = node_to_item(node, struct audio_usecase, list);
3493 if (usecase->type == PCM_PLAYBACK) {
3494 select_devices(adev, usecase->id);
3495 break;
3496 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003497 }
3498 }
3499 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003500 }
3501
Mingming Yin514a8bc2014-07-29 15:22:21 -07003502 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3503 if (ret >= 0) {
3504 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3505 adev->bt_wb_speech_enabled = true;
3506 else
3507 adev->bt_wb_speech_enabled = false;
3508 }
3509
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003510 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3511 if (ret >= 0) {
3512 val = atoi(value);
3513 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3514 ALOGV("cache new edid");
3515 platform_cache_edid(adev->platform);
3516 }
3517 }
3518
3519 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3520 if (ret >= 0) {
3521 val = atoi(value);
3522 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3523 ALOGV("invalidate cached edid");
3524 platform_invalidate_edid(adev->platform);
3525 }
3526 }
3527
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003528 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003529
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003530done:
3531 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003532 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303533error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003534 ALOGV("%s: exit with code(%d)", __func__, status);
3535 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536}
3537
3538static char* adev_get_parameters(const struct audio_hw_device *dev,
3539 const char *keys)
3540{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003541 struct audio_device *adev = (struct audio_device *)dev;
3542 struct str_parms *reply = str_parms_create();
3543 struct str_parms *query = str_parms_create_str(keys);
3544 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303545 char value[256] = {0};
3546 int ret = 0;
3547
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003548 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003549 if (reply) {
3550 str_parms_destroy(reply);
3551 }
3552 if (query) {
3553 str_parms_destroy(query);
3554 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003555 ALOGE("adev_get_parameters: failed to create query or reply");
3556 return NULL;
3557 }
3558
Naresh Tannirud7205b62014-06-20 02:54:48 +05303559 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3560 sizeof(value));
3561 if (ret >=0) {
3562 int val = 1;
3563 pthread_mutex_lock(&adev->snd_card_status.lock);
3564 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3565 val = 0;
3566 pthread_mutex_unlock(&adev->snd_card_status.lock);
3567 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3568 goto exit;
3569 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003570
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003571 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003572 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003573 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003574 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303575 pthread_mutex_unlock(&adev->lock);
3576
Naresh Tannirud7205b62014-06-20 02:54:48 +05303577exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003578 str = str_parms_to_str(reply);
3579 str_parms_destroy(query);
3580 str_parms_destroy(reply);
3581
3582 ALOGV("%s: exit: returns - %s", __func__, str);
3583 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584}
3585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003586static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 return 0;
3589}
3590
3591static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3592{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003593 int ret;
3594 struct audio_device *adev = (struct audio_device *)dev;
3595 pthread_mutex_lock(&adev->lock);
3596 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003597 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003598 pthread_mutex_unlock(&adev->lock);
3599 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003602static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3603 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604{
3605 return -ENOSYS;
3606}
3607
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3609 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610{
3611 return -ENOSYS;
3612}
3613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003614static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3615 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616{
3617 return -ENOSYS;
3618}
3619
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003620static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3621 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622{
3623 return -ENOSYS;
3624}
3625
3626static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3627{
3628 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 pthread_mutex_lock(&adev->lock);
3631 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003632 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003634 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003635 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003636 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003637 adev->current_call_output = NULL;
3638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 }
3640 pthread_mutex_unlock(&adev->lock);
3641 return 0;
3642}
3643
3644static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3645{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003646 int ret;
3647
3648 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003649 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003650 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3651 pthread_mutex_unlock(&adev->lock);
3652
3653 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654}
3655
3656static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3657{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003658 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 return 0;
3660}
3661
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003662static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 const struct audio_config *config)
3664{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003665 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003667 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3668 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
3671static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003672 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 audio_devices_t devices,
3674 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003675 struct audio_stream_in **stream_in,
3676 audio_input_flags_t flags __unused,
3677 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003678 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679{
3680 struct audio_device *adev = (struct audio_device *)dev;
3681 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003682 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003683 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003684 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 *stream_in = NULL;
3687 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3688 return -EINVAL;
3689
3690 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003691
3692 if (!in) {
3693 ALOGE("failed to allocate input stream");
3694 return -ENOMEM;
3695 }
3696
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303697 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003698 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3699 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003701 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003702 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 in->stream.common.get_sample_rate = in_get_sample_rate;
3705 in->stream.common.set_sample_rate = in_set_sample_rate;
3706 in->stream.common.get_buffer_size = in_get_buffer_size;
3707 in->stream.common.get_channels = in_get_channels;
3708 in->stream.common.get_format = in_get_format;
3709 in->stream.common.set_format = in_set_format;
3710 in->stream.common.standby = in_standby;
3711 in->stream.common.dump = in_dump;
3712 in->stream.common.set_parameters = in_set_parameters;
3713 in->stream.common.get_parameters = in_get_parameters;
3714 in->stream.common.add_audio_effect = in_add_audio_effect;
3715 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3716 in->stream.set_gain = in_set_gain;
3717 in->stream.read = in_read;
3718 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3719
3720 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003721 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 in->standby = 1;
3724 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003725 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003726 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727
3728 /* Update config params with the requested sample rate and channels */
3729 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003730 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3731 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3732 is_low_latency = true;
3733#if LOW_LATENCY_CAPTURE_USE_CASE
3734 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3735#endif
3736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003739 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003741 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303742 if (adev->mode != AUDIO_MODE_IN_CALL) {
3743 ret = -EINVAL;
3744 goto err_open;
3745 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003746 if (config->sample_rate == 0)
3747 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3748 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3749 config->sample_rate != 8000) {
3750 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3751 ret = -EINVAL;
3752 goto err_open;
3753 }
3754 if (config->format == AUDIO_FORMAT_DEFAULT)
3755 config->format = AUDIO_FORMAT_PCM_16_BIT;
3756 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3757 config->format = AUDIO_FORMAT_PCM_16_BIT;
3758 ret = -EINVAL;
3759 goto err_open;
3760 }
3761
3762 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3763 in->config = pcm_config_afe_proxy_record;
3764 in->config.channels = channel_count;
3765 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303766 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3767 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003768 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003769 audio_extn_compr_cap_format_supported(config->format) &&
3770 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003771 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003772 } else {
3773 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003774 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003775 buffer_size = get_input_buffer_size(config->sample_rate,
3776 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003777 channel_count,
3778 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003779 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003780 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3781 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3782 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3783 (in->config.rate == 8000 || in->config.rate == 16000) &&
3784 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3785 voice_extn_compress_voip_open_input_stream(in);
3786 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003789 /* This stream could be for sound trigger lab,
3790 get sound trigger pcm if present */
3791 audio_extn_sound_trigger_check_and_get_session(in);
3792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003794 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003795 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
3797err_open:
3798 free(in);
3799 *stream_in = NULL;
3800 return ret;
3801}
3802
3803static void adev_close_input_stream(struct audio_hw_device *dev,
3804 struct audio_stream_in *stream)
3805{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003806 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003807 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003808 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303809
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303810 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003811
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303812 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003813 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303814
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003815 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303816 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003817 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303818 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003819 if (ret != 0)
3820 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3821 __func__, ret);
3822 } else
3823 in_standby(&stream->common);
3824
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003825 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003826 audio_extn_ssr_deinit();
3827 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828
Mingming Yine62d7842013-10-25 16:26:03 -07003829 if(audio_extn_compr_cap_enabled() &&
3830 audio_extn_compr_cap_format_supported(in->config.format))
3831 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003832
3833 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 return;
3835}
3836
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003837static int adev_dump(const audio_hw_device_t *device __unused,
3838 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839{
3840 return 0;
3841}
3842
3843static int adev_close(hw_device_t *device)
3844{
3845 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003846
3847 if (!adev)
3848 return 0;
3849
3850 pthread_mutex_lock(&adev_init_lock);
3851
3852 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003853 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003854 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003855 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003856 audio_route_free(adev->audio_route);
3857 free(adev->snd_dev_ref_cnt);
3858 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003859 if (adev->adm_deinit)
3860 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003861 free(device);
3862 adev = NULL;
3863 }
3864 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 return 0;
3867}
3868
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003869/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3870 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3871 * just that it _might_ work.
3872 */
3873static int period_size_is_plausible_for_low_latency(int period_size)
3874{
3875 switch (period_size) {
3876 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003877 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003878 case 240:
3879 case 320:
3880 case 480:
3881 return 1;
3882 default:
3883 return 0;
3884 }
3885}
3886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887static int adev_open(const hw_module_t *module, const char *name,
3888 hw_device_t **device)
3889{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003890 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003892 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3894
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003895 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003896 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003897 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003898 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003899 ALOGD("%s: returning existing instance of adev", __func__);
3900 ALOGD("%s: exit", __func__);
3901 pthread_mutex_unlock(&adev_init_lock);
3902 return 0;
3903 }
3904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 adev = calloc(1, sizeof(struct audio_device));
3906
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003907 if (!adev) {
3908 pthread_mutex_unlock(&adev_init_lock);
3909 return -ENOMEM;
3910 }
3911
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003912 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3915 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3916 adev->device.common.module = (struct hw_module_t *)module;
3917 adev->device.common.close = adev_close;
3918
3919 adev->device.init_check = adev_init_check;
3920 adev->device.set_voice_volume = adev_set_voice_volume;
3921 adev->device.set_master_volume = adev_set_master_volume;
3922 adev->device.get_master_volume = adev_get_master_volume;
3923 adev->device.set_master_mute = adev_set_master_mute;
3924 adev->device.get_master_mute = adev_get_master_mute;
3925 adev->device.set_mode = adev_set_mode;
3926 adev->device.set_mic_mute = adev_set_mic_mute;
3927 adev->device.get_mic_mute = adev_get_mic_mute;
3928 adev->device.set_parameters = adev_set_parameters;
3929 adev->device.get_parameters = adev_get_parameters;
3930 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3931 adev->device.open_output_stream = adev_open_output_stream;
3932 adev->device.close_output_stream = adev_close_output_stream;
3933 adev->device.open_input_stream = adev_open_input_stream;
3934 adev->device.close_input_stream = adev_close_input_stream;
3935 adev->device.dump = adev_dump;
3936
3937 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003939 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003940 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003943 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003944 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003945 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003946 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003947 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003948 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003949 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303950 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303951 adev->perf_lock_opts[0] = 0x101;
3952 adev->perf_lock_opts[1] = 0x20E;
3953 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303954
3955 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3956 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003958 adev->platform = platform_init(adev);
3959 if (!adev->platform) {
3960 free(adev->snd_dev_ref_cnt);
3961 free(adev);
3962 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3963 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003964 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003965 return -EINVAL;
3966 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003967
Naresh Tanniru4c630392014-05-12 01:05:52 +05303968 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3969
Eric Laurentc4aef752013-09-12 17:45:53 -07003970 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3971 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3972 if (adev->visualizer_lib == NULL) {
3973 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3974 } else {
3975 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3976 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003977 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003978 "visualizer_hal_start_output");
3979 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003980 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003981 "visualizer_hal_stop_output");
3982 }
3983 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003984 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003985 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003986
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003987 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3988 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3989 if (adev->offload_effects_lib == NULL) {
3990 ALOGE("%s: DLOPEN failed for %s", __func__,
3991 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3992 } else {
3993 ALOGV("%s: DLOPEN successful for %s", __func__,
3994 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3995 adev->offload_effects_start_output =
3996 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3997 "offload_effects_bundle_hal_start_output");
3998 adev->offload_effects_stop_output =
3999 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4000 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004001 adev->offload_effects_set_hpx_state =
4002 (int (*)(bool))dlsym(adev->offload_effects_lib,
4003 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304004 adev->offload_effects_get_parameters =
4005 (void (*)(struct str_parms *, struct str_parms *))
4006 dlsym(adev->offload_effects_lib,
4007 "offload_effects_bundle_get_parameters");
4008 adev->offload_effects_set_parameters =
4009 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4010 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004011 }
4012 }
4013
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004014 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4015 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4016 if (adev->adm_lib == NULL) {
4017 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4018 } else {
4019 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4020 adev->adm_init = (adm_init_t)
4021 dlsym(adev->adm_lib, "adm_init");
4022 adev->adm_deinit = (adm_deinit_t)
4023 dlsym(adev->adm_lib, "adm_deinit");
4024 adev->adm_register_input_stream = (adm_register_input_stream_t)
4025 dlsym(adev->adm_lib, "adm_register_input_stream");
4026 adev->adm_register_output_stream = (adm_register_output_stream_t)
4027 dlsym(adev->adm_lib, "adm_register_output_stream");
4028 adev->adm_deregister_stream = (adm_deregister_stream_t)
4029 dlsym(adev->adm_lib, "adm_deregister_stream");
4030 adev->adm_request_focus = (adm_request_focus_t)
4031 dlsym(adev->adm_lib, "adm_request_focus");
4032 adev->adm_abandon_focus = (adm_abandon_focus_t)
4033 dlsym(adev->adm_lib, "adm_abandon_focus");
4034 }
4035 }
4036
Mingming Yin514a8bc2014-07-29 15:22:21 -07004037 adev->bt_wb_speech_enabled = false;
4038
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004039 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 *device = &adev->device.common;
4041
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004042 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4043 &adev->streams_output_cfg_list);
4044
Kiran Kandi910e1862013-10-29 13:29:42 -07004045 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004046
4047 char value[PROPERTY_VALUE_MAX];
4048 int trial;
4049 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4050 trial = atoi(value);
4051 if (period_size_is_plausible_for_low_latency(trial)) {
4052 pcm_config_low_latency.period_size = trial;
4053 pcm_config_low_latency.start_threshold = trial / 4;
4054 pcm_config_low_latency.avail_min = trial / 4;
4055 configured_low_latency_capture_period_size = trial;
4056 }
4057 }
4058 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4059 trial = atoi(value);
4060 if (period_size_is_plausible_for_low_latency(trial)) {
4061 configured_low_latency_capture_period_size = trial;
4062 }
4063 }
4064
vivek mehta446c3962015-09-14 10:57:35 -07004065 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004066 pthread_mutex_unlock(&adev_init_lock);
4067
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004068 if (adev->adm_init)
4069 adev->adm_data = adev->adm_init();
4070
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304071 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004072 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073 return 0;
4074}
4075
4076static struct hw_module_methods_t hal_module_methods = {
4077 .open = adev_open,
4078};
4079
4080struct audio_module HAL_MODULE_INFO_SYM = {
4081 .common = {
4082 .tag = HARDWARE_MODULE_TAG,
4083 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4084 .hal_api_version = HARDWARE_HAL_API_VERSION,
4085 .id = AUDIO_HARDWARE_MODULE_ID,
4086 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004087 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 .methods = &hal_module_methods,
4089 },
4090};