blob: e3d7d6a0b8b5bcd1e26c1e19b072b7e8e1e99739 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700180 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700183 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700185 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700186 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800187 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800188 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700190
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700191 [USECASE_VOICE2_CALL] = "voice2-call",
192 [USECASE_VOLTE_CALL] = "volte-call",
193 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800194 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800195 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
196 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800197 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700198 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
199 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
200 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800201 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
202 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
203 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
204
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700205 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
206 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700207 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
208 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700209
210 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
211 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700212};
213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700214static const audio_usecase_t offload_usecases[] = {
215 USECASE_AUDIO_PLAYBACK_OFFLOAD,
216#ifdef MULTIPLE_OFFLOAD_ENABLED
217 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
225#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700226 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700227};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228
229#define STRING_TO_ENUM(string) { #string, string }
230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800231struct string_to_enum {
232 const char *name;
233 uint32_t value;
234};
235
236static const struct string_to_enum out_channels_name_to_enum_table[] = {
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
244};
245
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700246static const struct string_to_enum out_formats_name_to_enum_table[] = {
247 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
250};
251
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700252static struct audio_device *adev = NULL;
253static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700254static unsigned int audio_device_ref_count;
255
Haynes Mathew George5191a852013-09-11 14:19:36 -0700256static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800257
vivek mehtaa76401a2015-04-24 14:12:15 -0700258__attribute__ ((visibility ("default")))
259bool audio_hw_send_gain_dep_calibration(int level) {
260 bool ret_val = false;
261 ALOGV("%s: called ... ", __func__);
262
263 pthread_mutex_lock(&adev_init_lock);
264
265 if (adev != NULL && adev->platform != NULL) {
266 pthread_mutex_lock(&adev->lock);
267 ret_val = platform_send_gain_dep_cal(adev->platform, level);
268 pthread_mutex_unlock(&adev->lock);
269 } else {
270 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
271 }
272
273 pthread_mutex_unlock(&adev_init_lock);
274
275 return ret_val;
276}
277
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800278static int check_and_set_gapless_mode(struct audio_device *adev) {
279
280
281 char value[PROPERTY_VALUE_MAX] = {0};
282 bool gapless_enabled = false;
283 const char *mixer_ctl_name = "Compress Gapless Playback";
284 struct mixer_ctl *ctl;
285
286 ALOGV("%s:", __func__);
287 property_get("audio.offload.gapless.enabled", value, NULL);
288 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
289
290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
291 if (!ctl) {
292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
293 __func__, mixer_ctl_name);
294 return -EINVAL;
295 }
296
297 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
298 ALOGE("%s: Could not set gapless mode %d",
299 __func__, gapless_enabled);
300 return -EINVAL;
301 }
302 return 0;
303}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305static bool is_supported_format(audio_format_t format)
306{
Eric Laurent86e17132013-09-12 17:49:30 -0700307 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530308 format == AUDIO_FORMAT_AAC_LC ||
309 format == AUDIO_FORMAT_AAC_HE_V1 ||
310 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530311 format == AUDIO_FORMAT_AAC_ADTS_LC ||
312 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800314 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700316 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 format == AUDIO_FORMAT_ALAC ||
319 format == AUDIO_FORMAT_APE ||
320 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800321 format == AUDIO_FORMAT_WMA ||
322 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800323 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700324
325 return false;
326}
327
328static int get_snd_codec_id(audio_format_t format)
329{
330 int id = 0;
331
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 case AUDIO_FORMAT_MP3:
334 id = SND_AUDIOCODEC_MP3;
335 break;
336 case AUDIO_FORMAT_AAC:
337 id = SND_AUDIOCODEC_AAC;
338 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530339 case AUDIO_FORMAT_AAC_ADTS:
340 id = SND_AUDIOCODEC_AAC;
341 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530342 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700343 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800344 id = SND_AUDIOCODEC_PCM;
345 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700346 case AUDIO_FORMAT_FLAC:
347 id = SND_AUDIOCODEC_FLAC;
348 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530349 case AUDIO_FORMAT_ALAC:
350 id = SND_AUDIOCODEC_ALAC;
351 break;
352 case AUDIO_FORMAT_APE:
353 id = SND_AUDIOCODEC_APE;
354 break;
355 case AUDIO_FORMAT_VORBIS:
356 id = SND_AUDIOCODEC_VORBIS;
357 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800358 case AUDIO_FORMAT_WMA:
359 id = SND_AUDIOCODEC_WMA;
360 break;
361 case AUDIO_FORMAT_WMA_PRO:
362 id = SND_AUDIOCODEC_WMA_PRO;
363 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700364 default:
Mingming Yin90310102013-11-13 16:57:00 -0800365 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700366 }
367
368 return id;
369}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800370
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530371int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530372{
373 int snd_scard_state;
374
375 if (!adev)
376 return SND_CARD_STATE_OFFLINE;
377
378 pthread_mutex_lock(&adev->snd_card_status.lock);
379 snd_scard_state = adev->snd_card_status.state;
380 pthread_mutex_unlock(&adev->snd_card_status.lock);
381
382 return snd_scard_state;
383}
384
385static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
386{
387 if (!adev)
388 return -ENOSYS;
389
390 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700391 if (adev->snd_card_status.state != snd_scard_state) {
392 adev->snd_card_status.state = snd_scard_state;
393 platform_snd_card_update(adev->platform, snd_scard_state);
394 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530395 pthread_mutex_unlock(&adev->snd_card_status.lock);
396
397 return 0;
398}
399
Avinash Vaish71a8b972014-07-24 15:36:33 +0530400static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
401 struct audio_usecase *uc_info)
402{
403 struct listnode *node;
404 struct audio_usecase *usecase;
405
406 if (uc_info == NULL)
407 return -EINVAL;
408
409 /* Re-route all voice usecases on the shared backend other than the
410 specified usecase to new snd devices */
411 list_for_each(node, &adev->usecase_list) {
412 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800413 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530414 enable_audio_route(adev, usecase);
415 }
416 return 0;
417}
418
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700419int pcm_ioctl(struct pcm *pcm, int request, ...)
420{
421 va_list ap;
422 void * arg;
423 int pcm_fd = *(int*)pcm;
424
425 va_start(ap, request);
426 arg = va_arg(ap, void *);
427 va_end(ap);
428
429 return ioctl(pcm_fd, request, arg);
430}
431
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700432int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700433 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700436 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437
438 if (usecase == NULL)
439 return -EINVAL;
440
441 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
442
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700444 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700446 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800447
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800448#ifdef DS1_DOLBY_DAP_ENABLED
449 audio_extn_dolby_set_dmid(adev);
450 audio_extn_dolby_set_endpoint(adev);
451#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700452 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700453 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530454 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700455 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700456 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800457 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700458 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700459 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
460 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461 ALOGV("%s: exit", __func__);
462 return 0;
463}
464
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700466 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700468 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700469 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800470
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530471 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800472 return -EINVAL;
473
474 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 if (usecase->type == PCM_CAPTURE)
476 snd_device = usecase->in_snd_device;
477 else
478 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800479 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700480 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700481 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
482 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700483 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530484 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485 ALOGV("%s: exit", __func__);
486 return 0;
487}
488
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700489int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700490 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700492 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
493
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800494 if (snd_device < SND_DEVICE_MIN ||
495 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800496 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800497 return -EINVAL;
498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499
500 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700501
502 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
503 ALOGE("%s: Invalid sound device returned", __func__);
504 return -EINVAL;
505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700506 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700507 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700508 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700509 return 0;
510 }
511
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700512 if (audio_extn_spkr_prot_is_enabled())
513 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700514 /* start usb playback thread */
515 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
516 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
517 audio_extn_usb_start_playback(adev);
518
519 /* start usb capture thread */
520 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
521 audio_extn_usb_start_capture(adev);
522
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700524 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
525 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
526 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
527 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700528 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
529 adev->snd_dev_ref_cnt[snd_device]--;
530 return -EINVAL;
531 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200532 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800533 if (audio_extn_spkr_prot_start_processing(snd_device)) {
534 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200535 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800536 return -EINVAL;
537 }
538 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700539 ALOGV("%s: snd_device(%d: %s)", __func__,
540 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700541 /* due to the possibility of calibration overwrite between listen
542 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700547 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700549 audio_extn_sound_trigger_update_device_status(snd_device,
550 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530551 audio_extn_listen_update_device_status(snd_device,
552 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700553 return -EINVAL;
554 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300555 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700556 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 return 0;
559}
560
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700561int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700564 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800566 if (snd_device < SND_DEVICE_MIN ||
567 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800568 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 return -EINVAL;
570 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
572 ALOGE("%s: device ref cnt is already 0", __func__);
573 return -EINVAL;
574 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700577
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
579 ALOGE("%s: Invalid sound device returned", __func__);
580 return -EINVAL;
581 }
582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700584 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700585 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800586 /* exit usb play back thread */
587 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
588 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
589 audio_extn_usb_stop_playback();
590
591 /* exit usb capture thread */
592 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700593 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800594
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800595 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700596 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
597 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
598 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
599 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700600 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300601 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700602 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300603 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700604
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200605 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700606 audio_extn_sound_trigger_update_device_status(snd_device,
607 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530608 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800609 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800612 return 0;
613}
614
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615static void check_usecases_codec_backend(struct audio_device *adev,
616 struct audio_usecase *uc_info,
617 snd_device_t snd_device)
618{
619 struct listnode *node;
620 struct audio_usecase *usecase;
621 bool switch_device[AUDIO_USECASE_MAX];
622 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800623 int backend_idx = DEFAULT_CODEC_BACKEND;
624 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625
626 /*
627 * This function is to make sure that all the usecases that are active on
628 * the hardware codec backend are always routed to any one device that is
629 * handled by the hardware codec.
630 * For example, if low-latency and deep-buffer usecases are currently active
631 * on speaker and out_set_parameters(headset) is received on low-latency
632 * output, then we have to make sure deep-buffer is also switched to headset,
633 * because of the limitation that both the devices cannot be enabled
634 * at the same time as they share the same backend.
635 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700636 /*
637 * This call is to check if we need to force routing for a particular stream
638 * If there is a backend configuration change for the device when a
639 * new stream starts, then ADM needs to be closed and re-opened with the new
640 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800641 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700642 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800643 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
644 snd_device);
645 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800647 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800648 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700649 for (i = 0; i < AUDIO_USECASE_MAX; i++)
650 switch_device[i] = false;
651
652 list_for_each(node, &adev->usecase_list) {
653 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800654
655 if (usecase == uc_info)
656 continue;
657 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
658 ALOGV("%s: backend_idx: %d,"
659 "usecase_backend_idx: %d, curr device: %s, usecase device:"
660 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530661 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800662
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800663 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700664 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800665 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
666 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530667 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800668 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700669 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700670 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 switch_device[usecase->id] = true;
672 num_uc_to_switch++;
673 }
674 }
675
676 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700677 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530679 /* Make sure the previous devices to be disabled first and then enable the
680 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 list_for_each(node, &adev->usecase_list) {
682 usecase = node_to_item(node, struct audio_usecase, list);
683 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700684 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 }
686 }
687
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
690 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700691 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700692 }
693 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695 /* Re-route all the usecases on the shared backend other than the
696 specified usecase to new snd devices */
697 list_for_each(node, &adev->usecase_list) {
698 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530699 /* Update the out_snd_device only for the usecases that are enabled here */
700 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
701 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530702 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 }
706}
707
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700708static void check_and_route_capture_usecases(struct audio_device *adev,
709 struct audio_usecase *uc_info,
710 snd_device_t snd_device)
711{
712 struct listnode *node;
713 struct audio_usecase *usecase;
714 bool switch_device[AUDIO_USECASE_MAX];
715 int i, num_uc_to_switch = 0;
716
717 /*
718 * This function is to make sure that all the active capture usecases
719 * are always routed to the same input sound device.
720 * For example, if audio-record and voice-call usecases are currently
721 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
722 * is received for voice call then we have to make sure that audio-record
723 * usecase is also switched to earpiece i.e. voice-dmic-ef,
724 * because of the limitation that two devices cannot be enabled
725 * at the same time if they share the same backend.
726 */
727 for (i = 0; i < AUDIO_USECASE_MAX; i++)
728 switch_device[i] = false;
729
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800732 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700734 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700735 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
736 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700737 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
739 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700740 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700741 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 switch_device[usecase->id] = true;
743 num_uc_to_switch++;
744 }
745 }
746
747 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700748 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530750 /* Make sure the previous devices to be disabled first and then enable the
751 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700752 list_for_each(node, &adev->usecase_list) {
753 usecase = node_to_item(node, struct audio_usecase, list);
754 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700755 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800756 }
757 }
758
759 list_for_each(node, &adev->usecase_list) {
760 usecase = node_to_item(node, struct audio_usecase, list);
761 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700762 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 }
764 }
765
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 /* Re-route all the usecases on the shared backend other than the
767 specified usecase to new snd devices */
768 list_for_each(node, &adev->usecase_list) {
769 usecase = node_to_item(node, struct audio_usecase, list);
770 /* Update the in_snd_device only before enabling the audio route */
771 if (switch_device[usecase->id] ) {
772 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800773 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530774 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700775 }
776 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700777 }
778}
779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700781static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700783 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700784 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800785
786 switch (channels) {
787 /*
788 * Do not handle stereo output in Multi-channel cases
789 * Stereo case is handled in normal playback path
790 */
791 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700792 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800798 break;
799 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700800 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
804 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
806 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 break;
808 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700809 ALOGE("HDMI does not support multi channel playback");
810 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800811 break;
812 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700813 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814}
815
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800816audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
817 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818{
819 struct audio_usecase *usecase;
820 struct listnode *node;
821
822 list_for_each(node, &adev->usecase_list) {
823 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800824 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700825 ALOGV("%s: usecase id %d", __func__, usecase->id);
826 return usecase->id;
827 }
828 }
829 return USECASE_INVALID;
830}
831
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700832struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700833 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834{
835 struct audio_usecase *usecase;
836 struct listnode *node;
837
838 list_for_each(node, &adev->usecase_list) {
839 usecase = node_to_item(node, struct audio_usecase, list);
840 if (usecase->id == uc_id)
841 return usecase;
842 }
843 return NULL;
844}
845
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700846int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800848 snd_device_t out_snd_device = SND_DEVICE_NONE;
849 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 struct audio_usecase *usecase = NULL;
851 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800852 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800853 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800854 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800855 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858 usecase = get_usecase_from_list(adev, uc_id);
859 if (usecase == NULL) {
860 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
861 return -EINVAL;
862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800864 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800865 (usecase->type == VOIP_CALL) ||
866 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700867 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800868 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 usecase->devices = usecase->stream.out->devices;
871 } else {
872 /*
873 * If the voice call is active, use the sound devices of voice call usecase
874 * so that it would not result any device switch. All the usecases will
875 * be switched to new device when select_devices() is called for voice call
876 * usecase. This is to avoid switching devices for voice call when
877 * check_usecases_codec_backend() is called below.
878 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700879 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700880 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800881 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700882 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
883 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 in_snd_device = vc_usecase->in_snd_device;
885 out_snd_device = vc_usecase->out_snd_device;
886 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800887 } else if (voice_extn_compress_voip_is_active(adev)) {
888 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700889 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530890 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700891 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800892 in_snd_device = voip_usecase->in_snd_device;
893 out_snd_device = voip_usecase->out_snd_device;
894 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800895 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800896 hfp_ucid = audio_extn_hfp_get_usecase();
897 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700898 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800899 in_snd_device = hfp_usecase->in_snd_device;
900 out_snd_device = hfp_usecase->out_snd_device;
901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 }
903 if (usecase->type == PCM_PLAYBACK) {
904 usecase->devices = usecase->stream.out->devices;
905 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700907 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800908 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 if (usecase->stream.out == adev->primary_output &&
910 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800911 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700912 select_devices(adev, adev->active_input->usecase);
913 }
914 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 } else if (usecase->type == PCM_CAPTURE) {
916 usecase->devices = usecase->stream.in->device;
917 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700918 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700919 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530920 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
921 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
922 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
923 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700924 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700925 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700926 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
927 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700928 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700929 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700930 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 }
932 }
933
934 if (out_snd_device == usecase->out_snd_device &&
935 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800936 return 0;
937 }
938
sangwoobc677242013-08-08 16:53:43 +0900939 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700940 out_snd_device, platform_get_snd_device_name(out_snd_device),
941 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943 /*
944 * Limitation: While in call, to do a device switch we need to disable
945 * and enable both RX and TX devices though one of them is same as current
946 * device.
947 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700948 if ((usecase->type == VOICE_CALL) &&
949 (usecase->in_snd_device != SND_DEVICE_NONE) &&
950 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700951 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700952 }
953
954 if (((usecase->type == VOICE_CALL) ||
955 (usecase->type == VOIP_CALL)) &&
956 (usecase->out_snd_device != SND_DEVICE_NONE)) {
957 /* Disable sidetone only if voice/voip call already exists */
958 if (voice_is_call_state_active(adev) ||
959 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700960 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800961 }
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 /* Disable current sound devices */
964 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700965 disable_audio_route(adev, usecase);
966 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967 }
968
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700970 disable_audio_route(adev, usecase);
971 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 }
973
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800974 /* Applicable only on the targets that has external modem.
975 * New device information should be sent to modem before enabling
976 * the devices to reduce in-call device switch time.
977 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700978 if ((usecase->type == VOICE_CALL) &&
979 (usecase->in_snd_device != SND_DEVICE_NONE) &&
980 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800981 status = platform_switch_voice_call_enable_device_config(adev->platform,
982 out_snd_device,
983 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700984 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800985
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 /* Enable new sound devices */
987 if (out_snd_device != SND_DEVICE_NONE) {
988 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
989 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700990 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 }
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 if (in_snd_device != SND_DEVICE_NONE) {
994 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700995 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997
Avinash Vaish71a8b972014-07-24 15:36:33 +0530998 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700999 status = platform_switch_voice_call_device_post(adev->platform,
1000 out_snd_device,
1001 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301002 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001003 /* Enable sidetone only if voice/voip call already exists */
1004 if (voice_is_call_state_active(adev) ||
1005 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001006 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301007 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001008
sangwoo170731f2013-06-08 15:36:36 +09001009 usecase->in_snd_device = in_snd_device;
1010 usecase->out_snd_device = out_snd_device;
1011
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301012 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001013 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301014 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001015 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301016 usecase->stream.out->flags,
1017 usecase->stream.out->format,
1018 usecase->stream.out->sample_rate,
1019 usecase->stream.out->bit_width,
1020 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001021 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301022 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001023
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001024 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001025
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001026 /* Applicable only on the targets that has external modem.
1027 * Enable device command should be sent to modem only after
1028 * enabling voice call mixer controls
1029 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001030 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001031 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1032 out_snd_device,
1033 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301034 ALOGD("%s: done",__func__);
1035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 return status;
1037}
1038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039static int stop_input_stream(struct stream_in *in)
1040{
1041 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 struct audio_usecase *uc_info;
1043 struct audio_device *adev = in->dev;
1044
Eric Laurentc8400632013-02-14 19:04:54 -08001045 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049 uc_info = get_usecase_from_list(adev, in->usecase);
1050 if (uc_info == NULL) {
1051 ALOGE("%s: Could not find the usecase (%d) in the list",
1052 __func__, in->usecase);
1053 return -EINVAL;
1054 }
1055
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001056 /* Close in-call recording streams */
1057 voice_check_and_stop_incall_rec_usecase(adev, in);
1058
Eric Laurent150dbfe2013-02-27 14:31:02 -08001059 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001060 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061
1062 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001063 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001065 list_remove(&uc_info->list);
1066 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067
Eric Laurent994a6932013-07-17 11:51:42 -07001068 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 return ret;
1070}
1071
1072int start_input_stream(struct stream_in *in)
1073{
1074 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001075 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076 struct audio_usecase *uc_info;
1077 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301078 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079
Mingming Yin2664a5b2015-09-03 10:53:11 -07001080 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1081 if (get_usecase_from_list(adev, usecase) == NULL)
1082 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301083 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1084 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001085
Naresh Tanniru80659832014-06-04 18:17:56 +05301086
1087 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301088 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301089 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301090 goto error_config;
1091 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301092
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001093 /* Check if source matches incall recording usecase criteria */
1094 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1095 if (ret)
1096 goto error_config;
1097 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001098 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1099
1100 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1101 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1102 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1103 goto error_config;
1104 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001105
Eric Laurentb23d5282013-05-14 15:27:20 -07001106 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 if (in->pcm_device_id < 0) {
1108 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1109 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001110 ret = -EINVAL;
1111 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113
1114 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001116
1117 if (!uc_info) {
1118 ret = -ENOMEM;
1119 goto error_config;
1120 }
1121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122 uc_info->id = in->usecase;
1123 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001124 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 uc_info->devices = in->device;
1126 uc_info->in_snd_device = SND_DEVICE_NONE;
1127 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001129 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301130 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132
Eric Laurentc8400632013-02-14 19:04:54 -08001133 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001134 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1135
1136 unsigned int flags = PCM_IN;
1137 unsigned int pcm_open_retry_count = 0;
1138
1139 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1140 flags |= PCM_MMAP | PCM_NOIRQ;
1141 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1142 }
1143
1144 while (1) {
1145 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1146 flags, &in->config);
1147 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1148 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1149 if (in->pcm != NULL) {
1150 pcm_close(in->pcm);
1151 in->pcm = NULL;
1152 }
1153 if (pcm_open_retry_count-- == 0) {
1154 ret = -EIO;
1155 goto error_open;
1156 }
1157 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1158 continue;
1159 }
1160 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301162 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301163
Eric Laurent994a6932013-07-17 11:51:42 -07001164 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001165 return ret;
1166
1167error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301169 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001170
1171error_config:
1172 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001174
1175 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176}
1177
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001178/* must be called with out->lock locked */
1179static int send_offload_cmd_l(struct stream_out* out, int command)
1180{
1181 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1182
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001183 if (!cmd) {
1184 ALOGE("failed to allocate mem for command 0x%x", command);
1185 return -ENOMEM;
1186 }
1187
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001188 ALOGVV("%s %d", __func__, command);
1189
1190 cmd->cmd = command;
1191 list_add_tail(&out->offload_cmd_list, &cmd->node);
1192 pthread_cond_signal(&out->offload_cond);
1193 return 0;
1194}
1195
1196/* must be called iwth out->lock locked */
1197static void stop_compressed_output_l(struct stream_out *out)
1198{
1199 out->offload_state = OFFLOAD_STATE_IDLE;
1200 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001201 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001202 if (out->compr != NULL) {
1203 compress_stop(out->compr);
1204 while (out->offload_thread_blocked) {
1205 pthread_cond_wait(&out->cond, &out->lock);
1206 }
1207 }
1208}
1209
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001210bool is_offload_usecase(audio_usecase_t uc_id)
1211{
1212 unsigned int i;
1213 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1214 if (uc_id == offload_usecases[i])
1215 return true;
1216 }
1217 return false;
1218}
1219
1220static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1221{
1222 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1223 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1224 char value[PROPERTY_VALUE_MAX] = {0};
1225
1226 property_get("audio.offload.multiple.enabled", value, NULL);
1227 if (!(atoi(value) || !strncmp("true", value, 4)))
1228 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1229
1230 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1231 for (i = 0; i < num_usecase; i++) {
1232 if (!(adev->offload_usecases_state & (0x1<<i))) {
1233 adev->offload_usecases_state |= 0x1 << i;
1234 ret = offload_usecases[i];
1235 break;
1236 }
1237 }
1238 ALOGV("%s: offload usecase is %d", __func__, ret);
1239 return ret;
1240}
1241
1242static void free_offload_usecase(struct audio_device *adev,
1243 audio_usecase_t uc_id)
1244{
1245 unsigned int i;
1246 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1247 if (offload_usecases[i] == uc_id) {
1248 adev->offload_usecases_state &= ~(0x1<<i);
1249 break;
1250 }
1251 }
1252 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1253}
1254
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001255static void *offload_thread_loop(void *context)
1256{
1257 struct stream_out *out = (struct stream_out *) context;
1258 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001259 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001261 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1262 set_sched_policy(0, SP_FOREGROUND);
1263 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1264
1265 ALOGV("%s", __func__);
1266 pthread_mutex_lock(&out->lock);
1267 for (;;) {
1268 struct offload_cmd *cmd = NULL;
1269 stream_callback_event_t event;
1270 bool send_callback = false;
1271
1272 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1273 __func__, list_empty(&out->offload_cmd_list),
1274 out->offload_state);
1275 if (list_empty(&out->offload_cmd_list)) {
1276 ALOGV("%s SLEEPING", __func__);
1277 pthread_cond_wait(&out->offload_cond, &out->lock);
1278 ALOGV("%s RUNNING", __func__);
1279 continue;
1280 }
1281
1282 item = list_head(&out->offload_cmd_list);
1283 cmd = node_to_item(item, struct offload_cmd, node);
1284 list_remove(item);
1285
1286 ALOGVV("%s STATE %d CMD %d out->compr %p",
1287 __func__, out->offload_state, cmd->cmd, out->compr);
1288
1289 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1290 free(cmd);
1291 break;
1292 }
1293
1294 if (out->compr == NULL) {
1295 ALOGE("%s: Compress handle is NULL", __func__);
1296 pthread_cond_signal(&out->cond);
1297 continue;
1298 }
1299 out->offload_thread_blocked = true;
1300 pthread_mutex_unlock(&out->lock);
1301 send_callback = false;
1302 switch(cmd->cmd) {
1303 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001304 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001306 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 send_callback = true;
1308 event = STREAM_CBK_EVENT_WRITE_READY;
1309 break;
1310 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001311 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301312 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001313 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301314 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001315 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301316 if (ret < 0)
1317 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301318 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301319 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001320 compress_drain(out->compr);
1321 else
1322 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301323 if (ret != -ENETRESET) {
1324 send_callback = true;
1325 event = STREAM_CBK_EVENT_DRAIN_READY;
1326 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1327 } else
1328 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 break;
1330 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001331 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001333 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001334 send_callback = true;
1335 event = STREAM_CBK_EVENT_DRAIN_READY;
1336 break;
1337 default:
1338 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1339 break;
1340 }
1341 pthread_mutex_lock(&out->lock);
1342 out->offload_thread_blocked = false;
1343 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001344 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001345 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001346 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001347 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001348 free(cmd);
1349 }
1350
1351 pthread_cond_signal(&out->cond);
1352 while (!list_empty(&out->offload_cmd_list)) {
1353 item = list_head(&out->offload_cmd_list);
1354 list_remove(item);
1355 free(node_to_item(item, struct offload_cmd, node));
1356 }
1357 pthread_mutex_unlock(&out->lock);
1358
1359 return NULL;
1360}
1361
1362static int create_offload_callback_thread(struct stream_out *out)
1363{
1364 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1365 list_init(&out->offload_cmd_list);
1366 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1367 offload_thread_loop, out);
1368 return 0;
1369}
1370
1371static int destroy_offload_callback_thread(struct stream_out *out)
1372{
1373 pthread_mutex_lock(&out->lock);
1374 stop_compressed_output_l(out);
1375 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1376
1377 pthread_mutex_unlock(&out->lock);
1378 pthread_join(out->offload_thread, (void **) NULL);
1379 pthread_cond_destroy(&out->offload_cond);
1380
1381 return 0;
1382}
1383
Eric Laurent07eeafd2013-10-06 12:52:49 -07001384static bool allow_hdmi_channel_config(struct audio_device *adev)
1385{
1386 struct listnode *node;
1387 struct audio_usecase *usecase;
1388 bool ret = true;
1389
1390 list_for_each(node, &adev->usecase_list) {
1391 usecase = node_to_item(node, struct audio_usecase, list);
1392 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1393 /*
1394 * If voice call is already existing, do not proceed further to avoid
1395 * disabling/enabling both RX and TX devices, CSD calls, etc.
1396 * Once the voice call done, the HDMI channels can be configured to
1397 * max channels of remaining use cases.
1398 */
1399 if (usecase->id == USECASE_VOICE_CALL) {
1400 ALOGD("%s: voice call is active, no change in HDMI channels",
1401 __func__);
1402 ret = false;
1403 break;
1404 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1405 ALOGD("%s: multi channel playback is active, "
1406 "no change in HDMI channels", __func__);
1407 ret = false;
1408 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001409 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001410 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001411 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1412 ", no change in HDMI channels", __func__,
1413 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001414 ret = false;
1415 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 }
1417 }
1418 }
1419 return ret;
1420}
1421
1422static int check_and_set_hdmi_channels(struct audio_device *adev,
1423 unsigned int channels)
1424{
1425 struct listnode *node;
1426 struct audio_usecase *usecase;
1427
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001428 unsigned int supported_channels = platform_edid_get_max_channels(
1429 adev->platform);
1430 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 /* Check if change in HDMI channel config is allowed */
1432 if (!allow_hdmi_channel_config(adev))
1433 return 0;
1434
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001435 if (channels > supported_channels)
1436 channels = supported_channels;
1437
Eric Laurent07eeafd2013-10-06 12:52:49 -07001438 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001439 ALOGD("%s: Requested channels are same as current channels(%d)",
1440 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001441 return 0;
1442 }
1443
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001444 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001446 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001447 adev->cur_hdmi_channels = channels;
1448
1449 /*
1450 * Deroute all the playback streams routed to HDMI so that
1451 * the back end is deactivated. Note that backend will not
1452 * be deactivated if any one stream is connected to it.
1453 */
1454 list_for_each(node, &adev->usecase_list) {
1455 usecase = node_to_item(node, struct audio_usecase, list);
1456 if (usecase->type == PCM_PLAYBACK &&
1457 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001458 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001459 }
1460 }
1461
1462 /*
1463 * Enable all the streams disabled above. Now the HDMI backend
1464 * will be activated with new channel configuration
1465 */
1466 list_for_each(node, &adev->usecase_list) {
1467 usecase = node_to_item(node, struct audio_usecase, list);
1468 if (usecase->type == PCM_PLAYBACK &&
1469 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001470 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001471 }
1472 }
1473
1474 return 0;
1475}
1476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477static int stop_output_stream(struct stream_out *out)
1478{
1479 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 struct audio_usecase *uc_info;
1481 struct audio_device *adev = out->dev;
1482
Eric Laurent994a6932013-07-17 11:51:42 -07001483 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 uc_info = get_usecase_from_list(adev, out->usecase);
1486 if (uc_info == NULL) {
1487 ALOGE("%s: Could not find the usecase (%d) in the list",
1488 __func__, out->usecase);
1489 return -EINVAL;
1490 }
1491
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001492 if (is_offload_usecase(out->usecase) &&
1493 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001494 if (adev->visualizer_stop_output != NULL)
1495 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001496
1497 audio_extn_dts_remove_state_notifier_node(out->usecase);
1498
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001499 if (adev->offload_effects_stop_output != NULL)
1500 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1501 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001502
Eric Laurent150dbfe2013-02-27 14:31:02 -08001503 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505
1506 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001507 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001509 list_remove(&uc_info->list);
1510 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001512 if (is_offload_usecase(out->usecase) &&
1513 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1514 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1515 ALOGV("Disable passthrough , reset mixer to pcm");
1516 /* NO_PASSTHROUGH */
1517 out->compr_config.codec->compr_passthr = 0;
1518 audio_extn_dolby_set_hdmi_config(adev, out);
1519 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1520 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521 /* Must be called after removing the usecase from list */
1522 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1523 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1524
Eric Laurent994a6932013-07-17 11:51:42 -07001525 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 return ret;
1527}
1528
1529int start_output_stream(struct stream_out *out)
1530{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001532 int sink_channels = 0;
1533 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 struct audio_usecase *uc_info;
1535 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301536 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001538 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1539 ret = -EINVAL;
1540 goto error_config;
1541 }
1542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301543 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1544 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1545 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301546
Naresh Tanniru80659832014-06-04 18:17:56 +05301547 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301548 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301549 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301550 goto error_config;
1551 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301552
Eric Laurentb23d5282013-05-14 15:27:20 -07001553 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 if (out->pcm_device_id < 0) {
1555 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1556 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001557 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 }
1560
1561 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001562
1563 if (!uc_info) {
1564 ret = -ENOMEM;
1565 goto error_config;
1566 }
1567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 uc_info->id = out->usecase;
1569 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001570 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 uc_info->devices = out->devices;
1572 uc_info->in_snd_device = SND_DEVICE_NONE;
1573 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001574 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001575 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001576 if (is_offload_usecase(out->usecase)) {
1577 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001578 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1579 }
1580 }
Mingming Yin9c041392014-05-01 15:37:31 -07001581 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1582 if (!strncmp("true", prop_value, 4)) {
1583 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1585 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001586 check_and_set_hdmi_channels(adev, sink_channels);
1587 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001588 if (is_offload_usecase(out->usecase)) {
1589 unsigned int ch_count = out->compr_config.codec->ch_in;
1590 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1591 /* backend channel config for passthrough stream is stereo */
1592 ch_count = 2;
1593 check_and_set_hdmi_channels(adev, ch_count);
1594 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001595 check_and_set_hdmi_channels(adev, out->config.channels);
1596 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001597 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001598 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001599 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 select_devices(adev, out->usecase);
1602
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1604 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001605 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001606 unsigned int flags = PCM_OUT;
1607 unsigned int pcm_open_retry_count = 0;
1608 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1609 flags |= PCM_MMAP | PCM_NOIRQ;
1610 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1611 } else
1612 flags |= PCM_MONOTONIC;
1613
1614 while (1) {
1615 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1616 flags, &out->config);
1617 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1618 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1619 if (out->pcm != NULL) {
1620 pcm_close(out->pcm);
1621 out->pcm = NULL;
1622 }
1623 if (pcm_open_retry_count-- == 0) {
1624 ret = -EIO;
1625 goto error_open;
1626 }
1627 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1628 continue;
1629 }
1630 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001631 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001632 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1633 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001634 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001635 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1636 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001638 out->compr = compress_open(adev->snd_card,
1639 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001640 COMPRESS_IN, &out->compr_config);
1641 if (out->compr && !is_compress_ready(out->compr)) {
1642 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1643 compress_close(out->compr);
1644 out->compr = NULL;
1645 ret = -EIO;
1646 goto error_open;
1647 }
1648 if (out->offload_callback)
1649 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001650
Fred Oh3f43e742015-03-04 18:42:34 -08001651 /* Since small bufs uses blocking writes, a write will be blocked
1652 for the default max poll time (20s) in the event of an SSR.
1653 Reduce the poll time to observe and deal with SSR faster.
1654 */
1655 if (out->use_small_bufs) {
1656 compress_set_max_poll_wait(out->compr, 1000);
1657 }
1658
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001659 audio_extn_dts_create_state_notifier_node(out->usecase);
1660 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1661 popcount(out->channel_mask),
1662 out->playback_started);
1663
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001664#ifdef DS1_DOLBY_DDP_ENABLED
1665 if (audio_extn_is_dolby_format(out->format))
1666 audio_extn_dolby_send_ddp_endp_params(adev);
1667#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001668 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1669 if (adev->visualizer_start_output != NULL)
1670 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1671 if (adev->offload_effects_start_output != NULL)
1672 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001673 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 }
Eric Laurent994a6932013-07-17 11:51:42 -07001676 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001680error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682}
1683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684static int check_input_parameters(uint32_t sample_rate,
1685 audio_format_t format,
1686 int channel_count)
1687{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001688 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001690 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001691 !voice_extn_compress_voip_is_format_supported(format) &&
1692 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001693
1694 switch (channel_count) {
1695 case 1:
1696 case 2:
1697 case 6:
1698 break;
1699 default:
1700 ret = -EINVAL;
1701 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
1703 switch (sample_rate) {
1704 case 8000:
1705 case 11025:
1706 case 12000:
1707 case 16000:
1708 case 22050:
1709 case 24000:
1710 case 32000:
1711 case 44100:
1712 case 48000:
1713 break;
1714 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001715 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 }
1717
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001718 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719}
1720
1721static size_t get_input_buffer_size(uint32_t sample_rate,
1722 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001723 int channel_count,
1724 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725{
1726 size_t size = 0;
1727
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001728 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1729 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001731 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001732 if (is_low_latency)
1733 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001734 /* ToDo: should use frame_size computed based on the format and
1735 channel_count here. */
1736 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001738 /* make sure the size is multiple of 32 bytes
1739 * At 48 kHz mono 16-bit PCM:
1740 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1741 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1742 */
1743 size += 0x1f;
1744 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001745
1746 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747}
1748
1749static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1750{
1751 struct stream_out *out = (struct stream_out *)stream;
1752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001756static int out_set_sample_rate(struct audio_stream *stream __unused,
1757 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758{
1759 return -ENOSYS;
1760}
1761
1762static size_t out_get_buffer_size(const struct audio_stream *stream)
1763{
1764 struct stream_out *out = (struct stream_out *)stream;
1765
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001766 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001768 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1769 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001771 return out->config.period_size *
1772 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773}
1774
1775static uint32_t out_get_channels(const struct audio_stream *stream)
1776{
1777 struct stream_out *out = (struct stream_out *)stream;
1778
1779 return out->channel_mask;
1780}
1781
1782static audio_format_t out_get_format(const struct audio_stream *stream)
1783{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 struct stream_out *out = (struct stream_out *)stream;
1785
1786 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787}
1788
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001789static int out_set_format(struct audio_stream *stream __unused,
1790 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791{
1792 return -ENOSYS;
1793}
1794
1795static int out_standby(struct audio_stream *stream)
1796{
1797 struct stream_out *out = (struct stream_out *)stream;
1798 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301800 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1801 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001802 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1803 /* Ignore standby in case of voip call because the voip output
1804 * stream is closed in adev_close_output_stream()
1805 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301806 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001807 return 0;
1808 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001810 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001812 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001814 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001815 if (out->pcm) {
1816 pcm_close(out->pcm);
1817 out->pcm = NULL;
1818 }
1819 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001820 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 out->gapless_mdata.encoder_delay = 0;
1823 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 if (out->compr != NULL) {
1825 compress_close(out->compr);
1826 out->compr = NULL;
1827 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001828 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001830 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 }
1832 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001833 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 return 0;
1835}
1836
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001837static int out_dump(const struct audio_stream *stream __unused,
1838 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839{
1840 return 0;
1841}
1842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1844{
1845 int ret = 0;
1846 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001847 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001848
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001850 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 return -EINVAL;
1852 }
1853
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301854 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001855
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001856 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1857 if(ret >= 0)
1858 is_meta_data_params = true;
1859 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301860 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001861 is_meta_data_params = true;
1862 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301863 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001864 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1866 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001867 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301868 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1871 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001872 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301873 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 }
1875
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001876 if(!is_meta_data_params) {
1877 ALOGV("%s: Not gapless meta data params", __func__);
1878 return 0;
1879 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001880 out->send_new_metadata = 1;
1881 ALOGV("%s new encoder delay %u and padding %u", __func__,
1882 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1883
1884 return 0;
1885}
1886
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001887static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1888{
1889 return out == adev->primary_output || out == adev->voice_tx_output;
1890}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1893{
1894 struct stream_out *out = (struct stream_out *)stream;
1895 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001896 struct audio_usecase *usecase;
1897 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 struct str_parms *parms;
1899 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001900 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001901 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
sangwoobc677242013-08-08 16:53:43 +09001903 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301906 if (!parms)
1907 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001908 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1909 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001912 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001914 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301915 * When HDMI cable is unplugged/usb hs is disconnected the
1916 * music playback is paused and the policy manager sends routing=0
1917 * But the audioflingercontinues to write data until standby time
1918 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 * Avoid this by routing audio to speaker until standby.
1920 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301921 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1922 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001923 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001924 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1925 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 }
1927
1928 /*
1929 * select_devices() call below switches all the usecases on the same
1930 * backend to the new device. Refer to check_usecases_codec_backend() in
1931 * the select_devices(). But how do we undo this?
1932 *
1933 * For example, music playback is active on headset (deep-buffer usecase)
1934 * and if we go to ringtones and select a ringtone, low-latency usecase
1935 * will be started on headset+speaker. As we can't enable headset+speaker
1936 * and headset devices at the same time, select_devices() switches the music
1937 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1938 * So when the ringtone playback is completed, how do we undo the same?
1939 *
1940 * We are relying on the out_set_parameters() call on deep-buffer output,
1941 * once the ringtone playback is ended.
1942 * NOTE: We should not check if the current devices are same as new devices.
1943 * Because select_devices() must be called to switch back the music
1944 * playback to headset.
1945 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001946 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 out->devices = val;
1948
1949 if (!out->standby)
1950 select_devices(adev, out->usecase);
1951
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001952 if (output_drives_call(adev, out)) {
1953 if(!voice_is_in_call(adev)) {
1954 if (adev->mode == AUDIO_MODE_IN_CALL) {
1955 adev->current_call_output = out;
1956 ret = voice_start_call(adev);
1957 }
1958 } else {
1959 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001960 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001961 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001962 }
1963 }
1964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001966 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001968
1969 if (out == adev->primary_output) {
1970 pthread_mutex_lock(&adev->lock);
1971 audio_extn_set_parameters(adev, parms);
1972 pthread_mutex_unlock(&adev->lock);
1973 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001975 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001976 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001977
1978 audio_extn_dts_create_state_notifier_node(out->usecase);
1979 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1980 popcount(out->channel_mask),
1981 out->playback_started);
1982
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001983 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001984 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301987error:
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 return ret;
1990}
1991
1992static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1993{
1994 struct stream_out *out = (struct stream_out *)stream;
1995 struct str_parms *query = str_parms_create_str(keys);
1996 char *str;
1997 char value[256];
1998 struct str_parms *reply = str_parms_create();
1999 size_t i, j;
2000 int ret;
2001 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002002
2003 if (!query || !reply) {
2004 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2005 return NULL;
2006 }
2007
Eric Laurent994a6932013-07-17 11:51:42 -07002008 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2010 if (ret >= 0) {
2011 value[0] = '\0';
2012 i = 0;
2013 while (out->supported_channel_masks[i] != 0) {
2014 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2015 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2016 if (!first) {
2017 strcat(value, "|");
2018 }
2019 strcat(value, out_channels_name_to_enum_table[j].name);
2020 first = false;
2021 break;
2022 }
2023 }
2024 i++;
2025 }
2026 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2027 str = str_parms_to_str(reply);
2028 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002029 voice_extn_out_get_parameters(out, query, reply);
2030 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002031 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002032 free(str);
2033 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002034 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002036
2037 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2038 if (ret >= 0) {
2039 value[0] = '\0';
2040 i = 0;
2041 first = true;
2042 while (out->supported_formats[i] != 0) {
2043 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2044 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2045 if (!first) {
2046 strcat(value, "|");
2047 }
2048 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2049 first = false;
2050 break;
2051 }
2052 }
2053 i++;
2054 }
2055 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2056 str = str_parms_to_str(reply);
2057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 str_parms_destroy(query);
2059 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002060 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 return str;
2062}
2063
2064static uint32_t out_get_latency(const struct audio_stream_out *stream)
2065{
2066 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002067 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Alexy Josephaa54c872014-12-03 02:46:47 -08002069 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002070 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002071 } else {
2072 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002074 }
2075
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302076 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002077 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078}
2079
2080static int out_set_volume(struct audio_stream_out *stream, float left,
2081 float right)
2082{
Eric Laurenta9024de2013-04-04 09:19:12 -07002083 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 int volume[2];
2085
Eric Laurenta9024de2013-04-04 09:19:12 -07002086 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2087 /* only take left channel into account: the API is for stereo anyway */
2088 out->muted = (left == 0.0f);
2089 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002090 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002091 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2092 /*
2093 * Set mute or umute on HDMI passthrough stream.
2094 * Only take left channel into account.
2095 * Mute is 0 and unmute 1
2096 */
2097 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2098 } else {
2099 char mixer_ctl_name[128];
2100 struct audio_device *adev = out->dev;
2101 struct mixer_ctl *ctl;
2102 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002103 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002105 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2106 "Compress Playback %d Volume", pcm_device_id);
2107 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2108 if (!ctl) {
2109 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2110 __func__, mixer_ctl_name);
2111 return -EINVAL;
2112 }
2113 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2114 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2115 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2116 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002118 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 return -ENOSYS;
2121}
2122
2123static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2124 size_t bytes)
2125{
2126 struct stream_out *out = (struct stream_out *)stream;
2127 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002129 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302132
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002134 // increase written size during SSR to avoid mismatch
2135 // with the written frames count in AF
2136 if (!is_offload_usecase(out->usecase))
2137 out->written += bytes / (out->config.channels * sizeof(short));
2138
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302140 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302141 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002143 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302144 //during SSR for compress usecase we should return error to flinger
2145 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2146 pthread_mutex_unlock(&out->lock);
2147 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302148 }
2149 }
2150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002152 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002153 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002154 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2155 ret = voice_extn_compress_voip_start_output_stream(out);
2156 else
2157 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002158 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002161 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 goto exit;
2163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002166 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002167 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002169 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2171 out->send_new_metadata = 0;
2172 }
2173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302175 if (ret < 0)
2176 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002177 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002178 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302179 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302181 } else if (-ENETRESET == ret) {
2182 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2184 pthread_mutex_unlock(&out->lock);
2185 out_standby(&out->stream.common);
2186 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002190 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 out->playback_started = 1;
2192 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002193
2194 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2195 popcount(out->channel_mask),
2196 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
2198 pthread_mutex_unlock(&out->lock);
2199 return ret;
2200 } else {
2201 if (out->pcm) {
2202 if (out->muted)
2203 memset((void *)buffer, 0, bytes);
2204 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002205 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2206 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2207 else
2208 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302209 if (ret < 0)
2210 ret = -errno;
2211 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002212 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 }
2215
2216exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302217 /* ToDo: There may be a corner case when SSR happens back to back during
2218 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302219 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302221 }
2222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 pthread_mutex_unlock(&out->lock);
2224
2225 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002226 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002227 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302228 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302229 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302230 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302231 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302232 out->standby = true;
2233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002235 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302236 out_get_sample_rate(&out->stream.common));
2237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
2239 return bytes;
2240}
2241
2242static int out_get_render_position(const struct audio_stream_out *stream,
2243 uint32_t *dsp_frames)
2244{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302246 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002247
2248 if (dsp_frames == NULL)
2249 return -EINVAL;
2250
2251 *dsp_frames = 0;
2252 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002253 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 pthread_mutex_lock(&out->lock);
2255 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302256 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302258 if (ret < 0)
2259 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 ALOGVV("%s rendered frames %d sample_rate %d",
2261 __func__, *dsp_frames, out->sample_rate);
2262 }
2263 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302264 if (-ENETRESET == ret) {
2265 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2266 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2267 return -EINVAL;
2268 } else if(ret < 0) {
2269 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2270 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302271 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2272 /*
2273 * Handle corner case where compress session is closed during SSR
2274 * and timestamp is queried
2275 */
2276 ALOGE(" ERROR: sound card not active, return error");
2277 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302278 } else {
2279 return 0;
2280 }
Zhou Song32a556e2015-05-05 10:46:56 +08002281 } else if (audio_is_linear_pcm(out->format)) {
2282 *dsp_frames = out->written;
2283 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 } else
2285 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286}
2287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002288static int out_add_audio_effect(const struct audio_stream *stream __unused,
2289 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290{
2291 return 0;
2292}
2293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002294static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2295 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296{
2297 return 0;
2298}
2299
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002300static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2301 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302{
2303 return -EINVAL;
2304}
2305
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002306static int out_get_presentation_position(const struct audio_stream_out *stream,
2307 uint64_t *frames, struct timespec *timestamp)
2308{
2309 struct stream_out *out = (struct stream_out *)stream;
2310 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002311 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002312
2313 pthread_mutex_lock(&out->lock);
2314
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002315 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002316 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302317 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002318 &out->sample_rate);
2319 ALOGVV("%s rendered frames %ld sample_rate %d",
2320 __func__, dsp_frames, out->sample_rate);
2321 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302322 if (ret < 0)
2323 ret = -errno;
2324 if (-ENETRESET == ret) {
2325 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2326 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2327 ret = -EINVAL;
2328 } else
2329 ret = 0;
2330
Eric Laurent949a0892013-09-20 09:20:13 -07002331 /* this is the best we can do */
2332 clock_gettime(CLOCK_MONOTONIC, timestamp);
2333 }
2334 } else {
2335 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002336 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002337 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2338 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002339 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002340 // This adjustment accounts for buffering after app processor.
2341 // It is based on estimated DSP latency per use case, rather than exact.
2342 signed_frames -=
2343 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2344
Eric Laurent949a0892013-09-20 09:20:13 -07002345 // It would be unusual for this value to be negative, but check just in case ...
2346 if (signed_frames >= 0) {
2347 *frames = signed_frames;
2348 ret = 0;
2349 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002350 }
2351 }
2352 }
2353
2354 pthread_mutex_unlock(&out->lock);
2355
2356 return ret;
2357}
2358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359static int out_set_callback(struct audio_stream_out *stream,
2360 stream_callback_t callback, void *cookie)
2361{
2362 struct stream_out *out = (struct stream_out *)stream;
2363
2364 ALOGV("%s", __func__);
2365 pthread_mutex_lock(&out->lock);
2366 out->offload_callback = callback;
2367 out->offload_cookie = cookie;
2368 pthread_mutex_unlock(&out->lock);
2369 return 0;
2370}
2371
2372static int out_pause(struct audio_stream_out* stream)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375 int status = -ENOSYS;
2376 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002377 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002378 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 pthread_mutex_lock(&out->lock);
2380 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302381 struct audio_device *adev = out->dev;
2382 int snd_scard_state = get_snd_card_state(adev);
2383
2384 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2385 status = compress_pause(out->compr);
2386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002388
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302389 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002390 audio_extn_dts_notify_playback_state(out->usecase, 0,
2391 out->sample_rate, popcount(out->channel_mask),
2392 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 }
2394 pthread_mutex_unlock(&out->lock);
2395 }
2396 return status;
2397}
2398
2399static int out_resume(struct audio_stream_out* stream)
2400{
2401 struct stream_out *out = (struct stream_out *)stream;
2402 int status = -ENOSYS;
2403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002404 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002405 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 status = 0;
2407 pthread_mutex_lock(&out->lock);
2408 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302409 struct audio_device *adev = out->dev;
2410 int snd_scard_state = get_snd_card_state(adev);
2411
2412 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2413 status = compress_resume(out->compr);
2414
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002416
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302417 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002418 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2419 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 }
2421 pthread_mutex_unlock(&out->lock);
2422 }
2423 return status;
2424}
2425
2426static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429 int status = -ENOSYS;
2430 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002431 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 pthread_mutex_lock(&out->lock);
2433 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2434 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2435 else
2436 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2437 pthread_mutex_unlock(&out->lock);
2438 }
2439 return status;
2440}
2441
2442static int out_flush(struct audio_stream_out* stream)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002446 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002447 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 pthread_mutex_lock(&out->lock);
2449 stop_compressed_output_l(out);
2450 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002451 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 return 0;
2453 }
2454 return -ENOSYS;
2455}
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457/** audio_stream_in implementation **/
2458static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2459{
2460 struct stream_in *in = (struct stream_in *)stream;
2461
2462 return in->config.rate;
2463}
2464
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002465static int in_set_sample_rate(struct audio_stream *stream __unused,
2466 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467{
2468 return -ENOSYS;
2469}
2470
2471static size_t in_get_buffer_size(const struct audio_stream *stream)
2472{
2473 struct stream_in *in = (struct stream_in *)stream;
2474
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002475 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2476 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002477 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2478 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002479
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002480 return in->config.period_size *
2481 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482}
2483
2484static uint32_t in_get_channels(const struct audio_stream *stream)
2485{
2486 struct stream_in *in = (struct stream_in *)stream;
2487
2488 return in->channel_mask;
2489}
2490
2491static audio_format_t in_get_format(const struct audio_stream *stream)
2492{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002493 struct stream_in *in = (struct stream_in *)stream;
2494
2495 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496}
2497
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002498static int in_set_format(struct audio_stream *stream __unused,
2499 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500{
2501 return -ENOSYS;
2502}
2503
2504static int in_standby(struct audio_stream *stream)
2505{
2506 struct stream_in *in = (struct stream_in *)stream;
2507 struct audio_device *adev = in->dev;
2508 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302509 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2510 stream, in->usecase, use_case_table[in->usecase]);
2511
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002512 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2513 /* Ignore standby in case of voip call because the voip input
2514 * stream is closed in adev_close_input_stream()
2515 */
2516 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2517 return status;
2518 }
2519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002521 if (!in->standby && in->is_st_session) {
2522 ALOGD("%s: sound trigger pcm stop lab", __func__);
2523 audio_extn_sound_trigger_stop_lab(in);
2524 in->standby = 1;
2525 }
2526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002528 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002530 if (in->pcm) {
2531 pcm_close(in->pcm);
2532 in->pcm = NULL;
2533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002535 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 }
2537 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002538 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 return status;
2540}
2541
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002542static int in_dump(const struct audio_stream *stream __unused,
2543 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544{
2545 return 0;
2546}
2547
2548static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2549{
2550 struct stream_in *in = (struct stream_in *)stream;
2551 struct audio_device *adev = in->dev;
2552 struct str_parms *parms;
2553 char *str;
2554 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002555 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302557 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 parms = str_parms_create_str(kvpairs);
2559
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302560 if (!parms)
2561 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002563 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002564
2565 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2566 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 val = atoi(value);
2568 /* no audio source uses val == 0 */
2569 if ((in->source != val) && (val != 0)) {
2570 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002571 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2572 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2573 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2574 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002575 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002576 err = voice_extn_compress_voip_open_input_stream(in);
2577 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002578 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002579 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002580 }
2581 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 }
2583 }
2584
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002585 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2586 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002588 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 in->device = val;
2590 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002591 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002592 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593 }
2594 }
2595
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002596done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002598 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
2600 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302601error:
Eric Laurent994a6932013-07-17 11:51:42 -07002602 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 return ret;
2604}
2605
2606static char* in_get_parameters(const struct audio_stream *stream,
2607 const char *keys)
2608{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002609 struct stream_in *in = (struct stream_in *)stream;
2610 struct str_parms *query = str_parms_create_str(keys);
2611 char *str;
2612 char value[256];
2613 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002614
2615 if (!query || !reply) {
2616 ALOGE("in_get_parameters: failed to create query or reply");
2617 return NULL;
2618 }
2619
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002620 ALOGV("%s: enter: keys - %s", __func__, keys);
2621
2622 voice_extn_in_get_parameters(in, query, reply);
2623
2624 str = str_parms_to_str(reply);
2625 str_parms_destroy(query);
2626 str_parms_destroy(reply);
2627
2628 ALOGV("%s: exit: returns - %s", __func__, str);
2629 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630}
2631
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002632static int in_set_gain(struct audio_stream_in *stream __unused,
2633 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634{
2635 return 0;
2636}
2637
2638static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2639 size_t bytes)
2640{
2641 struct stream_in *in = (struct stream_in *)stream;
2642 struct audio_device *adev = in->dev;
2643 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302644 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302647
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002648 if (in->is_st_session) {
2649 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2650 /* Read from sound trigger HAL */
2651 audio_extn_sound_trigger_read(in, buffer, bytes);
2652 pthread_mutex_unlock(&in->lock);
2653 return bytes;
2654 }
2655
2656 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2657 ALOGD(" %s: sound card is not active/SSR state", __func__);
2658 ret= -EIO;;
2659 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302660 }
2661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002663 pthread_mutex_lock(&adev->lock);
2664 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2665 ret = voice_extn_compress_voip_start_input_stream(in);
2666 else
2667 ret = start_input_stream(in);
2668 pthread_mutex_unlock(&adev->lock);
2669 if (ret != 0) {
2670 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672 in->standby = 0;
2673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674
2675 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002676 if (audio_extn_ssr_get_enabled() &&
2677 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002678 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002679 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2680 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002681 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2682 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002683 else
2684 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302685 if (ret < 0)
2686 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 }
2688
2689 /*
2690 * Instead of writing zeroes here, we could trust the hardware
2691 * to always provide zeroes when muted.
2692 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302693 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2694 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 memset(buffer, 0, bytes);
2696
2697exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302698 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302699 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002700 if (-ENETRESET == ret)
2701 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 pthread_mutex_unlock(&in->lock);
2704
2705 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302706 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302707 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302708 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302709 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302710 in->standby = true;
2711 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302712 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002714 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002715 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302716 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 }
2718 return bytes;
2719}
2720
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002721static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722{
2723 return 0;
2724}
2725
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002726static int add_remove_audio_effect(const struct audio_stream *stream,
2727 effect_handle_t effect,
2728 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002730 struct stream_in *in = (struct stream_in *)stream;
2731 int status = 0;
2732 effect_descriptor_t desc;
2733
2734 status = (*effect)->get_descriptor(effect, &desc);
2735 if (status != 0)
2736 return status;
2737
2738 pthread_mutex_lock(&in->lock);
2739 pthread_mutex_lock(&in->dev->lock);
2740 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2741 in->enable_aec != enable &&
2742 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2743 in->enable_aec = enable;
2744 if (!in->standby)
2745 select_devices(in->dev, in->usecase);
2746 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002747 if (in->enable_ns != enable &&
2748 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2749 in->enable_ns = enable;
2750 if (!in->standby)
2751 select_devices(in->dev, in->usecase);
2752 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002753 pthread_mutex_unlock(&in->dev->lock);
2754 pthread_mutex_unlock(&in->lock);
2755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 return 0;
2757}
2758
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002759static int in_add_audio_effect(const struct audio_stream *stream,
2760 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
Eric Laurent994a6932013-07-17 11:51:42 -07002762 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002763 return add_remove_audio_effect(stream, effect, true);
2764}
2765
2766static int in_remove_audio_effect(const struct audio_stream *stream,
2767 effect_handle_t effect)
2768{
Eric Laurent994a6932013-07-17 11:51:42 -07002769 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002770 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771}
2772
2773static int adev_open_output_stream(struct audio_hw_device *dev,
2774 audio_io_handle_t handle,
2775 audio_devices_t devices,
2776 audio_output_flags_t flags,
2777 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002778 struct audio_stream_out **stream_out,
2779 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780{
2781 struct audio_device *adev = (struct audio_device *)dev;
2782 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002783 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002784 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302787
2788 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2789 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002790 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302791 return -EINVAL;
2792 }
2793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2795
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302796 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2797 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2798 devices, flags, &out->stream);
2799
2800
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002801 if (!out) {
2802 return -ENOMEM;
2803 }
2804
Haynes Mathew George204045b2015-02-25 20:32:03 -08002805 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2806 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 if (devices == AUDIO_DEVICE_NONE)
2809 devices = AUDIO_DEVICE_OUT_SPEAKER;
2810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->flags = flags;
2812 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002813 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002814 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 out->sample_rate = config->sample_rate;
2816 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2817 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002818 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002819 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002820 out->non_blocking = 0;
2821 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
2823 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002824 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2825 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002826 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2827 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2828
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002829 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002830 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2831 ret = read_hdmi_channel_masks(out);
2832
2833 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2834 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002835 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002836 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002837 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002838
2839 if (config->sample_rate == 0)
2840 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2841 if (config->channel_mask == 0)
2842 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2843
2844 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2847 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002849 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002851 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2852 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002853 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002854 ret = voice_extn_compress_voip_open_output_stream(out);
2855 if (ret != 0) {
2856 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2857 __func__, ret);
2858 goto error_open;
2859 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002860 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2861 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2862
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2864 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2865 ALOGE("%s: Unsupported Offload information", __func__);
2866 ret = -EINVAL;
2867 goto error_open;
2868 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002869
2870 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2871 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2872 ALOGV("read and update_pass through formats");
2873 ret = audio_extn_dolby_update_passt_formats(adev, out);
2874 if(ret != 0) {
2875 goto error_open;
2876 }
2877 if(config->offload_info.format == 0)
2878 config->offload_info.format = out->supported_formats[0];
2879 }
2880
Mingming Yin90310102013-11-13 16:57:00 -08002881 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002882 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002883 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 ret = -EINVAL;
2885 goto error_open;
2886 }
2887
2888 out->compr_config.codec = (struct snd_codec *)
2889 calloc(1, sizeof(struct snd_codec));
2890
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002891 if (!out->compr_config.codec) {
2892 ret = -ENOMEM;
2893 goto error_open;
2894 }
2895
vivek mehta0ea887a2015-08-26 14:01:20 -07002896 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2897 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2898 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2899 } else {
2900 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2901 out->usecase = get_offload_usecase(adev);
2902 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 if (config->offload_info.channel_mask)
2904 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002905 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 config->offload_info.channel_mask = config->channel_mask;
2908 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002909 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 out->sample_rate = config->offload_info.sample_rate;
2911
2912 out->stream.set_callback = out_set_callback;
2913 out->stream.pause = out_pause;
2914 out->stream.resume = out_resume;
2915 out->stream.drain = out_drain;
2916 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002919 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002920 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002921 audio_extn_dolby_get_snd_codec_id(adev, out,
2922 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002923 else
2924 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002926
2927 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2928 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002930 platform_get_pcm_offload_buffer_size(&config->offload_info);
2931 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2932 out->compr_config.fragment_size =
2933 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002934 } else {
2935 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002936 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002937 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2939 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002940 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 out->compr_config.codec->bit_rate =
2942 config->offload_info.bit_rate;
2943 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002944 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302946 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002947 /*TODO: Do we need to change it for passthrough */
2948 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949
Manish Dewangana6fc5442015-08-24 20:30:31 +05302950 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2951 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2952 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2953 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002954 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2955 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002956 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002957 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002958 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2959 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002960
Mingming Yin3ee55c62014-08-04 14:23:35 -07002961 if (out->bit_width == 24) {
2962 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2963 }
2964
Amit Shekhar6f461b12014-08-01 14:52:58 -07002965 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302966 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002967
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002968 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2969 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002970
Mingming Yin497419f2015-07-01 16:57:32 -07002971 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002972 //this flag is set from framework only if its for PCM formats
2973 //no need to check for PCM format again
2974 out->non_blocking = 0;
2975 out->use_small_bufs = true;
2976 ALOGI("Keep write blocking for small buff: non_blockling %d",
2977 out->non_blocking);
2978 }
2979
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002980 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002981 out->offload_state = OFFLOAD_STATE_IDLE;
2982 out->playback_started = 0;
2983
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002984 audio_extn_dts_create_state_notifier_node(out->usecase);
2985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 create_offload_callback_thread(out);
2987 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2988 __func__, config->offload_info.version,
2989 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002990 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002991 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002992 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2993 ret = voice_check_and_set_incall_music_usecase(adev, out);
2994 if (ret != 0) {
2995 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2996 __func__, ret);
2997 goto error_open;
2998 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002999 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3000 if (config->sample_rate == 0)
3001 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3002 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3003 config->sample_rate != 8000) {
3004 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3005 ret = -EINVAL;
3006 goto error_open;
3007 }
3008 out->sample_rate = config->sample_rate;
3009 out->config.rate = config->sample_rate;
3010 if (config->format == AUDIO_FORMAT_DEFAULT)
3011 config->format = AUDIO_FORMAT_PCM_16_BIT;
3012 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3013 config->format = AUDIO_FORMAT_PCM_16_BIT;
3014 ret = -EINVAL;
3015 goto error_open;
3016 }
3017 out->format = config->format;
3018 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3019 out->config = pcm_config_afe_proxy_playback;
3020 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003021 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003022 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3024 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003026 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3027 format = AUDIO_FORMAT_PCM_16_BIT;
3028 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3029 out->config = pcm_config_deep_buffer;
3030 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003031 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003032 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003033 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003034 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003035 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003036 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 }
3038
Amit Shekhar1d896042014-10-03 13:16:09 -07003039 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3040 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003041 /* TODO remove this hardcoding and check why width is zero*/
3042 if (out->bit_width == 0)
3043 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003044 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3045 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003046 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003047 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003048 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3049 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3050 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003051 if(adev->primary_output == NULL)
3052 adev->primary_output = out;
3053 else {
3054 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003055 ret = -EEXIST;
3056 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003057 }
3058 }
3059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 /* Check if this usecase is already existing */
3061 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003062 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3063 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003066 ret = -EEXIST;
3067 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 }
3069 pthread_mutex_unlock(&adev->lock);
3070
3071 out->stream.common.get_sample_rate = out_get_sample_rate;
3072 out->stream.common.set_sample_rate = out_set_sample_rate;
3073 out->stream.common.get_buffer_size = out_get_buffer_size;
3074 out->stream.common.get_channels = out_get_channels;
3075 out->stream.common.get_format = out_get_format;
3076 out->stream.common.set_format = out_set_format;
3077 out->stream.common.standby = out_standby;
3078 out->stream.common.dump = out_dump;
3079 out->stream.common.set_parameters = out_set_parameters;
3080 out->stream.common.get_parameters = out_get_parameters;
3081 out->stream.common.add_audio_effect = out_add_audio_effect;
3082 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3083 out->stream.get_latency = out_get_latency;
3084 out->stream.set_volume = out_set_volume;
3085 out->stream.write = out_write;
3086 out->stream.get_render_position = out_get_render_position;
3087 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003088 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003091 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003092 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093
3094 config->format = out->stream.common.get_format(&out->stream.common);
3095 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3096 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3097
3098 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303099 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003100 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003101
3102 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3103 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3104 popcount(out->channel_mask), out->playback_started);
3105
Eric Laurent994a6932013-07-17 11:51:42 -07003106 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003108
3109error_open:
3110 free(out);
3111 *stream_out = NULL;
3112 ALOGD("%s: exit: ret %d", __func__, ret);
3113 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114}
3115
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003116static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 struct audio_stream_out *stream)
3118{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 struct stream_out *out = (struct stream_out *)stream;
3120 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003121 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303123 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3124
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003125 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303126 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003127 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303128 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003129 if(ret != 0)
3130 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3131 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003132 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003133 out_standby(&stream->common);
3134
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003135 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003136 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003138 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (out->compr_config.codec != NULL)
3140 free(out->compr_config.codec);
3141 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003142
3143 if (adev->voice_tx_output == out)
3144 adev->voice_tx_output = NULL;
3145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 pthread_cond_destroy(&out->cond);
3147 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003149 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150}
3151
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003152static void close_compress_sessions(struct audio_device *adev)
3153{
Mingming Yin7b762e72015-03-04 13:47:32 -08003154 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303155 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003156 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003157 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303158
3159 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003160 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303161 if (is_offload_usecase(usecase->id)) {
3162 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003163 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3164 out = usecase->stream.out;
3165 pthread_mutex_unlock(&adev->lock);
3166 out_standby(&out->stream.common);
3167 pthread_mutex_lock(&adev->lock);
3168 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303169 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003170 }
3171 pthread_mutex_unlock(&adev->lock);
3172}
3173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3175{
3176 struct audio_device *adev = (struct audio_device *)dev;
3177 struct str_parms *parms;
3178 char *str;
3179 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003180 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003181 int ret;
3182 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003184 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303187 if (!parms)
3188 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003189 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3190 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303191 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303192 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303193 struct listnode *node;
3194 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303195 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303196 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003197 //close compress sessions on OFFLINE status
3198 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303199 } else if (strstr(snd_card_status, "ONLINE")) {
3200 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303201 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003202 //send dts hpx license if enabled
3203 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303204 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303205 }
3206
3207 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003208 status = voice_set_parameters(adev, parms);
3209 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003210 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003212 status = platform_set_parameters(adev->platform, parms);
3213 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003214 goto done;
3215
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003216 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3217 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003218 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3220 adev->bluetooth_nrec = true;
3221 else
3222 adev->bluetooth_nrec = false;
3223 }
3224
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003225 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3226 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3228 adev->screen_off = false;
3229 else
3230 adev->screen_off = true;
3231 }
3232
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003233 ret = str_parms_get_int(parms, "rotation", &val);
3234 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003235 bool reverse_speakers = false;
3236 switch(val) {
3237 // FIXME: note that the code below assumes that the speakers are in the correct placement
3238 // relative to the user when the device is rotated 90deg from its default rotation. This
3239 // assumption is device-specific, not platform-specific like this code.
3240 case 270:
3241 reverse_speakers = true;
3242 break;
3243 case 0:
3244 case 90:
3245 case 180:
3246 break;
3247 default:
3248 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003249 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003250 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003251 if (status == 0) {
3252 if (adev->speaker_lr_swap != reverse_speakers) {
3253 adev->speaker_lr_swap = reverse_speakers;
3254 // only update the selected device if there is active pcm playback
3255 struct audio_usecase *usecase;
3256 struct listnode *node;
3257 list_for_each(node, &adev->usecase_list) {
3258 usecase = node_to_item(node, struct audio_usecase, list);
3259 if (usecase->type == PCM_PLAYBACK) {
3260 select_devices(adev, usecase->id);
3261 break;
3262 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003263 }
3264 }
3265 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003266 }
3267
Mingming Yin514a8bc2014-07-29 15:22:21 -07003268 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3269 if (ret >= 0) {
3270 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3271 adev->bt_wb_speech_enabled = true;
3272 else
3273 adev->bt_wb_speech_enabled = false;
3274 }
3275
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003276 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3277 if (ret >= 0) {
3278 val = atoi(value);
3279 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3280 ALOGV("cache new edid");
3281 platform_cache_edid(adev->platform);
3282 }
3283 }
3284
3285 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3286 if (ret >= 0) {
3287 val = atoi(value);
3288 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3289 ALOGV("invalidate cached edid");
3290 platform_invalidate_edid(adev->platform);
3291 }
3292 }
3293
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003294 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003295
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003296done:
3297 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003298 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303299error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003300 ALOGV("%s: exit with code(%d)", __func__, status);
3301 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302}
3303
3304static char* adev_get_parameters(const struct audio_hw_device *dev,
3305 const char *keys)
3306{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003307 struct audio_device *adev = (struct audio_device *)dev;
3308 struct str_parms *reply = str_parms_create();
3309 struct str_parms *query = str_parms_create_str(keys);
3310 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303311 char value[256] = {0};
3312 int ret = 0;
3313
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003314 if (!query || !reply) {
3315 ALOGE("adev_get_parameters: failed to create query or reply");
3316 return NULL;
3317 }
3318
Naresh Tannirud7205b62014-06-20 02:54:48 +05303319 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3320 sizeof(value));
3321 if (ret >=0) {
3322 int val = 1;
3323 pthread_mutex_lock(&adev->snd_card_status.lock);
3324 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3325 val = 0;
3326 pthread_mutex_unlock(&adev->snd_card_status.lock);
3327 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3328 goto exit;
3329 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003330
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003331 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003332 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003333 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003334 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303335 pthread_mutex_unlock(&adev->lock);
3336
Naresh Tannirud7205b62014-06-20 02:54:48 +05303337exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003338 str = str_parms_to_str(reply);
3339 str_parms_destroy(query);
3340 str_parms_destroy(reply);
3341
3342 ALOGV("%s: exit: returns - %s", __func__, str);
3343 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344}
3345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003346static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 return 0;
3349}
3350
3351static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3352{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003353 int ret;
3354 struct audio_device *adev = (struct audio_device *)dev;
3355 pthread_mutex_lock(&adev->lock);
3356 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003357 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003358 pthread_mutex_unlock(&adev->lock);
3359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003362static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3363 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364{
3365 return -ENOSYS;
3366}
3367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003368static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3369 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370{
3371 return -ENOSYS;
3372}
3373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003374static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3375 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376{
3377 return -ENOSYS;
3378}
3379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003380static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3381 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382{
3383 return -ENOSYS;
3384}
3385
3386static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3387{
3388 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 pthread_mutex_lock(&adev->lock);
3391 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003392 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003394 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3395 voice_is_in_call(adev)) {
3396 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003397 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003398 adev->current_call_output = NULL;
3399 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 }
3401 pthread_mutex_unlock(&adev->lock);
3402 return 0;
3403}
3404
3405static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3406{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003407 int ret;
3408
3409 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003410 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003411 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3412 pthread_mutex_unlock(&adev->lock);
3413
3414 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415}
3416
3417static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3418{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003419 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 return 0;
3421}
3422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003423static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 const struct audio_config *config)
3425{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003426 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003428 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3429 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430}
3431
3432static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003433 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 audio_devices_t devices,
3435 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003436 struct audio_stream_in **stream_in,
3437 audio_input_flags_t flags __unused,
3438 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003439 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
3441 struct audio_device *adev = (struct audio_device *)dev;
3442 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003443 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003444 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003445 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 *stream_in = NULL;
3448 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3449 return -EINVAL;
3450
3451 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003452
3453 if (!in) {
3454 ALOGE("failed to allocate input stream");
3455 return -ENOMEM;
3456 }
3457
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303458 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003459 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3460 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003462 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 in->stream.common.get_sample_rate = in_get_sample_rate;
3465 in->stream.common.set_sample_rate = in_set_sample_rate;
3466 in->stream.common.get_buffer_size = in_get_buffer_size;
3467 in->stream.common.get_channels = in_get_channels;
3468 in->stream.common.get_format = in_get_format;
3469 in->stream.common.set_format = in_set_format;
3470 in->stream.common.standby = in_standby;
3471 in->stream.common.dump = in_dump;
3472 in->stream.common.set_parameters = in_set_parameters;
3473 in->stream.common.get_parameters = in_get_parameters;
3474 in->stream.common.add_audio_effect = in_add_audio_effect;
3475 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3476 in->stream.set_gain = in_set_gain;
3477 in->stream.read = in_read;
3478 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3479
3480 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003481 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 in->standby = 1;
3484 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003485 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486
3487 /* Update config params with the requested sample rate and channels */
3488 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003489 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3490 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3491 is_low_latency = true;
3492#if LOW_LATENCY_CAPTURE_USE_CASE
3493 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3494#endif
3495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003498 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003500 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303501 if (adev->mode != AUDIO_MODE_IN_CALL) {
3502 ret = -EINVAL;
3503 goto err_open;
3504 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003505 if (config->sample_rate == 0)
3506 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3507 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3508 config->sample_rate != 8000) {
3509 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3510 ret = -EINVAL;
3511 goto err_open;
3512 }
3513 if (config->format == AUDIO_FORMAT_DEFAULT)
3514 config->format = AUDIO_FORMAT_PCM_16_BIT;
3515 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3516 config->format = AUDIO_FORMAT_PCM_16_BIT;
3517 ret = -EINVAL;
3518 goto err_open;
3519 }
3520
3521 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3522 in->config = pcm_config_afe_proxy_record;
3523 in->config.channels = channel_count;
3524 in->config.rate = config->sample_rate;
3525 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003526 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003527 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003528 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3529 ret = -EINVAL;
3530 goto err_open;
3531 }
3532 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003533 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003534 }
Mingming Yine62d7842013-10-25 16:26:03 -07003535 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003536 audio_extn_compr_cap_format_supported(config->format) &&
3537 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003538 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003539 } else {
3540 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003541 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003542 buffer_size = get_input_buffer_size(config->sample_rate,
3543 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003544 channel_count,
3545 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003546 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003547 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3548 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3549 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3550 (in->config.rate == 8000 || in->config.rate == 16000) &&
3551 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3552 voice_extn_compress_voip_open_input_stream(in);
3553 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003554 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003556 /* This stream could be for sound trigger lab,
3557 get sound trigger pcm if present */
3558 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303559 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003562 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003563 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
3565err_open:
3566 free(in);
3567 *stream_in = NULL;
3568 return ret;
3569}
3570
3571static void adev_close_input_stream(struct audio_hw_device *dev,
3572 struct audio_stream_in *stream)
3573{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003574 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003575 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003576 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303577
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303578 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003579
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303580 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003581 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303582
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003583 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303584 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003585 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303586 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003587 if (ret != 0)
3588 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3589 __func__, ret);
3590 } else
3591 in_standby(&stream->common);
3592
Mingming Yin7b762e72015-03-04 13:47:32 -08003593 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003594 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003595 audio_extn_ssr_deinit();
3596 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Mingming Yine62d7842013-10-25 16:26:03 -07003598 if(audio_extn_compr_cap_enabled() &&
3599 audio_extn_compr_cap_format_supported(in->config.format))
3600 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003601
3602 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 return;
3604}
3605
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003606static int adev_dump(const audio_hw_device_t *device __unused,
3607 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608{
3609 return 0;
3610}
3611
3612static int adev_close(hw_device_t *device)
3613{
3614 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003615
3616 if (!adev)
3617 return 0;
3618
3619 pthread_mutex_lock(&adev_init_lock);
3620
3621 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003622 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003623 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003624 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003625 audio_route_free(adev->audio_route);
3626 free(adev->snd_dev_ref_cnt);
3627 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003628 free(device);
3629 adev = NULL;
3630 }
3631 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 return 0;
3633}
3634
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003635/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3636 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3637 * just that it _might_ work.
3638 */
3639static int period_size_is_plausible_for_low_latency(int period_size)
3640{
3641 switch (period_size) {
3642 case 160:
3643 case 240:
3644 case 320:
3645 case 480:
3646 return 1;
3647 default:
3648 return 0;
3649 }
3650}
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652static int adev_open(const hw_module_t *module, const char *name,
3653 hw_device_t **device)
3654{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003655 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003657 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3659
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003660 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003661 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003662 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003663 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003664 ALOGD("%s: returning existing instance of adev", __func__);
3665 ALOGD("%s: exit", __func__);
3666 pthread_mutex_unlock(&adev_init_lock);
3667 return 0;
3668 }
3669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 adev = calloc(1, sizeof(struct audio_device));
3671
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003672 if (!adev) {
3673 pthread_mutex_unlock(&adev_init_lock);
3674 return -ENOMEM;
3675 }
3676
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003677 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3680 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3681 adev->device.common.module = (struct hw_module_t *)module;
3682 adev->device.common.close = adev_close;
3683
3684 adev->device.init_check = adev_init_check;
3685 adev->device.set_voice_volume = adev_set_voice_volume;
3686 adev->device.set_master_volume = adev_set_master_volume;
3687 adev->device.get_master_volume = adev_get_master_volume;
3688 adev->device.set_master_mute = adev_set_master_mute;
3689 adev->device.get_master_mute = adev_get_master_mute;
3690 adev->device.set_mode = adev_set_mode;
3691 adev->device.set_mic_mute = adev_set_mic_mute;
3692 adev->device.get_mic_mute = adev_get_mic_mute;
3693 adev->device.set_parameters = adev_set_parameters;
3694 adev->device.get_parameters = adev_get_parameters;
3695 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3696 adev->device.open_output_stream = adev_open_output_stream;
3697 adev->device.close_output_stream = adev_close_output_stream;
3698 adev->device.open_input_stream = adev_open_input_stream;
3699 adev->device.close_input_stream = adev_close_input_stream;
3700 adev->device.dump = adev_dump;
3701
3702 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003704 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003705 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003708 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003709 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003710 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003711 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003712 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003713 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003714 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303715
3716 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3717 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003719 adev->platform = platform_init(adev);
3720 if (!adev->platform) {
3721 free(adev->snd_dev_ref_cnt);
3722 free(adev);
3723 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3724 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003725 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003726 return -EINVAL;
3727 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003728
Naresh Tanniru4c630392014-05-12 01:05:52 +05303729 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3730
Eric Laurentc4aef752013-09-12 17:45:53 -07003731 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3732 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3733 if (adev->visualizer_lib == NULL) {
3734 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3735 } else {
3736 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3737 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003738 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003739 "visualizer_hal_start_output");
3740 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003741 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003742 "visualizer_hal_stop_output");
3743 }
3744 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003745 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003746 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003747
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003748 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3749 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3750 if (adev->offload_effects_lib == NULL) {
3751 ALOGE("%s: DLOPEN failed for %s", __func__,
3752 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3753 } else {
3754 ALOGV("%s: DLOPEN successful for %s", __func__,
3755 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3756 adev->offload_effects_start_output =
3757 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3758 "offload_effects_bundle_hal_start_output");
3759 adev->offload_effects_stop_output =
3760 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3761 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003762 adev->offload_effects_set_hpx_state =
3763 (int (*)(bool))dlsym(adev->offload_effects_lib,
3764 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003765 }
3766 }
3767
Mingming Yin514a8bc2014-07-29 15:22:21 -07003768 adev->bt_wb_speech_enabled = false;
3769
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003770 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 *device = &adev->device.common;
3772
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003773 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3774 &adev->streams_output_cfg_list);
3775
Kiran Kandi910e1862013-10-29 13:29:42 -07003776 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003777
3778 char value[PROPERTY_VALUE_MAX];
3779 int trial;
3780 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3781 trial = atoi(value);
3782 if (period_size_is_plausible_for_low_latency(trial)) {
3783 pcm_config_low_latency.period_size = trial;
3784 pcm_config_low_latency.start_threshold = trial / 4;
3785 pcm_config_low_latency.avail_min = trial / 4;
3786 configured_low_latency_capture_period_size = trial;
3787 }
3788 }
3789 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3790 trial = atoi(value);
3791 if (period_size_is_plausible_for_low_latency(trial)) {
3792 configured_low_latency_capture_period_size = trial;
3793 }
3794 }
3795
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003796 pthread_mutex_unlock(&adev_init_lock);
3797
Eric Laurent994a6932013-07-17 11:51:42 -07003798 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 return 0;
3800}
3801
3802static struct hw_module_methods_t hal_module_methods = {
3803 .open = adev_open,
3804};
3805
3806struct audio_module HAL_MODULE_INFO_SYM = {
3807 .common = {
3808 .tag = HARDWARE_MODULE_TAG,
3809 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3810 .hal_api_version = HARDWARE_HAL_API_VERSION,
3811 .id = AUDIO_HARDWARE_MODULE_ID,
3812 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003813 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 .methods = &hal_module_methods,
3815 },
3816};