blob: 4357d8dcc6d59f94c7ffc86d54d16d5e97c047e3 [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",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700171#ifdef MULTIPLE_OFFLOAD_ENABLED
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
180#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700181 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
217#ifdef MULTIPLE_OFFLOAD_ENABLED
218 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
225 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
226#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700227 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229
230#define STRING_TO_ENUM(string) { #string, string }
231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800232struct string_to_enum {
233 const char *name;
234 uint32_t value;
235};
236
237static const struct string_to_enum out_channels_name_to_enum_table[] = {
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
245};
246
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700247static const struct string_to_enum out_formats_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
250 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
251};
252
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700253static struct audio_device *adev = NULL;
254static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700255static unsigned int audio_device_ref_count;
256
Haynes Mathew George5191a852013-09-11 14:19:36 -0700257static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800258
vivek mehtaa76401a2015-04-24 14:12:15 -0700259__attribute__ ((visibility ("default")))
260bool audio_hw_send_gain_dep_calibration(int level) {
261 bool ret_val = false;
262 ALOGV("%s: called ... ", __func__);
263
264 pthread_mutex_lock(&adev_init_lock);
265
266 if (adev != NULL && adev->platform != NULL) {
267 pthread_mutex_lock(&adev->lock);
268 ret_val = platform_send_gain_dep_cal(adev->platform, level);
269 pthread_mutex_unlock(&adev->lock);
270 } else {
271 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
272 }
273
274 pthread_mutex_unlock(&adev_init_lock);
275
276 return ret_val;
277}
278
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800279static int check_and_set_gapless_mode(struct audio_device *adev) {
280
281
282 char value[PROPERTY_VALUE_MAX] = {0};
283 bool gapless_enabled = false;
284 const char *mixer_ctl_name = "Compress Gapless Playback";
285 struct mixer_ctl *ctl;
286
287 ALOGV("%s:", __func__);
288 property_get("audio.offload.gapless.enabled", value, NULL);
289 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
290
291 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
292 if (!ctl) {
293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
294 __func__, mixer_ctl_name);
295 return -EINVAL;
296 }
297
298 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
299 ALOGE("%s: Could not set gapless mode %d",
300 __func__, gapless_enabled);
301 return -EINVAL;
302 }
303 return 0;
304}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306static bool is_supported_format(audio_format_t format)
307{
Eric Laurent86e17132013-09-12 17:49:30 -0700308 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 format == AUDIO_FORMAT_AAC_LC ||
310 format == AUDIO_FORMAT_AAC_HE_V1 ||
311 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530312 format == AUDIO_FORMAT_AAC_ADTS_LC ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
314 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800315 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700317 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800318 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530319 format == AUDIO_FORMAT_ALAC ||
320 format == AUDIO_FORMAT_APE ||
321 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800322 format == AUDIO_FORMAT_WMA ||
323 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800324 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700325
326 return false;
327}
328
329static int get_snd_codec_id(audio_format_t format)
330{
331 int id = 0;
332
Ashish Jainf9b78162014-08-25 20:36:25 +0530333 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700334 case AUDIO_FORMAT_MP3:
335 id = SND_AUDIOCODEC_MP3;
336 break;
337 case AUDIO_FORMAT_AAC:
338 id = SND_AUDIOCODEC_AAC;
339 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530340 case AUDIO_FORMAT_AAC_ADTS:
341 id = SND_AUDIOCODEC_AAC;
342 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530343 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700344 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800345 id = SND_AUDIOCODEC_PCM;
346 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700347 case AUDIO_FORMAT_FLAC:
348 id = SND_AUDIOCODEC_FLAC;
349 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530350 case AUDIO_FORMAT_ALAC:
351 id = SND_AUDIOCODEC_ALAC;
352 break;
353 case AUDIO_FORMAT_APE:
354 id = SND_AUDIOCODEC_APE;
355 break;
356 case AUDIO_FORMAT_VORBIS:
357 id = SND_AUDIOCODEC_VORBIS;
358 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800359 case AUDIO_FORMAT_WMA:
360 id = SND_AUDIOCODEC_WMA;
361 break;
362 case AUDIO_FORMAT_WMA_PRO:
363 id = SND_AUDIOCODEC_WMA_PRO;
364 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700365 default:
Mingming Yin90310102013-11-13 16:57:00 -0800366 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700367 }
368
369 return id;
370}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800371
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530372int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530373{
374 int snd_scard_state;
375
376 if (!adev)
377 return SND_CARD_STATE_OFFLINE;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
380 snd_scard_state = adev->snd_card_status.state;
381 pthread_mutex_unlock(&adev->snd_card_status.lock);
382
383 return snd_scard_state;
384}
385
386static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
387{
388 if (!adev)
389 return -ENOSYS;
390
391 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700392 if (adev->snd_card_status.state != snd_scard_state) {
393 adev->snd_card_status.state = snd_scard_state;
394 platform_snd_card_update(adev->platform, snd_scard_state);
395 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530396 pthread_mutex_unlock(&adev->snd_card_status.lock);
397
398 return 0;
399}
400
Avinash Vaish71a8b972014-07-24 15:36:33 +0530401static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
402 struct audio_usecase *uc_info)
403{
404 struct listnode *node;
405 struct audio_usecase *usecase;
406
407 if (uc_info == NULL)
408 return -EINVAL;
409
410 /* Re-route all voice usecases on the shared backend other than the
411 specified usecase to new snd devices */
412 list_for_each(node, &adev->usecase_list) {
413 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800414 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530415 enable_audio_route(adev, usecase);
416 }
417 return 0;
418}
419
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700420int pcm_ioctl(struct pcm *pcm, int request, ...)
421{
422 va_list ap;
423 void * arg;
424 int pcm_fd = *(int*)pcm;
425
426 va_start(ap, request);
427 arg = va_arg(ap, void *);
428 va_end(ap);
429
430 return ioctl(pcm_fd, request, arg);
431}
432
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700433int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700434 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700436 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700437 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438
439 if (usecase == NULL)
440 return -EINVAL;
441
442 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
443
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800444 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800448
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800449#ifdef DS1_DOLBY_DAP_ENABLED
450 audio_extn_dolby_set_dmid(adev);
451 audio_extn_dolby_set_endpoint(adev);
452#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700453 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700454 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530455 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700456 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700457 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800458 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700459 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700460 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
461 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462 ALOGV("%s: exit", __func__);
463 return 0;
464}
465
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700466int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700467 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700470 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800471
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530472 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800473 return -EINVAL;
474
475 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700476 if (usecase->type == PCM_CAPTURE)
477 snd_device = usecase->in_snd_device;
478 else
479 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800480 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700481 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700482 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
483 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700484 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530485 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486 ALOGV("%s: exit", __func__);
487 return 0;
488}
489
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700490int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700491 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800492{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700493 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
494
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800495 if (snd_device < SND_DEVICE_MIN ||
496 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800497 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800498 return -EINVAL;
499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700500
501 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700502
503 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
504 ALOGE("%s: Invalid sound device returned", __func__);
505 return -EINVAL;
506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700508 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700509 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700510 return 0;
511 }
512
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700513 if (audio_extn_spkr_prot_is_enabled())
514 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700515 /* start usb playback thread */
516 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
517 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
518 audio_extn_usb_start_playback(adev);
519
520 /* start usb capture thread */
521 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
522 audio_extn_usb_start_capture(adev);
523
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800524 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
525 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700527 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
528 adev->snd_dev_ref_cnt[snd_device]--;
529 return -EINVAL;
530 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200531 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800532 if (audio_extn_spkr_prot_start_processing(snd_device)) {
533 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200534 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800535 return -EINVAL;
536 }
537 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700538 ALOGV("%s: snd_device(%d: %s)", __func__,
539 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700540 /* due to the possibility of calibration overwrite between listen
541 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700546 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700547 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700548 audio_extn_sound_trigger_update_device_status(snd_device,
549 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530550 audio_extn_listen_update_device_status(snd_device,
551 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700552 return -EINVAL;
553 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300554 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700555 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 return 0;
558}
559
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700560int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700561 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700563 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
564
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800565 if (snd_device < SND_DEVICE_MIN ||
566 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800567 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800568 return -EINVAL;
569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
571 ALOGE("%s: device ref cnt is already 0", __func__);
572 return -EINVAL;
573 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700574
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700576
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700577 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
578 ALOGE("%s: Invalid sound device returned", __func__);
579 return -EINVAL;
580 }
581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700583 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700584 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800585 /* exit usb play back thread */
586 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
587 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
588 audio_extn_usb_stop_playback();
589
590 /* exit usb capture thread */
591 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700592 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800593
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800594 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
595 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700596 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700597 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300598 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700599 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700601
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200602 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603 audio_extn_sound_trigger_update_device_status(snd_device,
604 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530605 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800606 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 return 0;
610}
611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612static void check_usecases_codec_backend(struct audio_device *adev,
613 struct audio_usecase *uc_info,
614 snd_device_t snd_device)
615{
616 struct listnode *node;
617 struct audio_usecase *usecase;
618 bool switch_device[AUDIO_USECASE_MAX];
619 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800620 int backend_idx = DEFAULT_CODEC_BACKEND;
621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622
623 /*
624 * This function is to make sure that all the usecases that are active on
625 * the hardware codec backend are always routed to any one device that is
626 * handled by the hardware codec.
627 * For example, if low-latency and deep-buffer usecases are currently active
628 * on speaker and out_set_parameters(headset) is received on low-latency
629 * output, then we have to make sure deep-buffer is also switched to headset,
630 * because of the limitation that both the devices cannot be enabled
631 * at the same time as they share the same backend.
632 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700633 /*
634 * This call is to check if we need to force routing for a particular stream
635 * If there is a backend configuration change for the device when a
636 * new stream starts, then ADM needs to be closed and re-opened with the new
637 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800638 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700639 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800640 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
641 snd_device);
642 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800644 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800645 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 for (i = 0; i < AUDIO_USECASE_MAX; i++)
647 switch_device[i] = false;
648
649 list_for_each(node, &adev->usecase_list) {
650 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651
652 if (usecase == uc_info)
653 continue;
654 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
655 ALOGV("%s: backend_idx: %d,"
656 "usecase_backend_idx: %d, curr device: %s, usecase device:"
657 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530658 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800660 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700661 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800662 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
663 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530664 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800665 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700666 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700667 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 switch_device[usecase->id] = true;
669 num_uc_to_switch++;
670 }
671 }
672
673 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700674 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530676 /* Make sure the previous devices to be disabled first and then enable the
677 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 list_for_each(node, &adev->usecase_list) {
679 usecase = node_to_item(node, struct audio_usecase, list);
680 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700681 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 }
683 }
684
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700685 list_for_each(node, &adev->usecase_list) {
686 usecase = node_to_item(node, struct audio_usecase, list);
687 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700688 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700689 }
690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692 /* Re-route all the usecases on the shared backend other than the
693 specified usecase to new snd devices */
694 list_for_each(node, &adev->usecase_list) {
695 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530696 /* Update the out_snd_device only for the usecases that are enabled here */
697 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
698 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530699 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 }
701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 }
703}
704
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700705static void check_and_route_capture_usecases(struct audio_device *adev,
706 struct audio_usecase *uc_info,
707 snd_device_t snd_device)
708{
709 struct listnode *node;
710 struct audio_usecase *usecase;
711 bool switch_device[AUDIO_USECASE_MAX];
712 int i, num_uc_to_switch = 0;
713
714 /*
715 * This function is to make sure that all the active capture usecases
716 * are always routed to the same input sound device.
717 * For example, if audio-record and voice-call usecases are currently
718 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
719 * is received for voice call then we have to make sure that audio-record
720 * usecase is also switched to earpiece i.e. voice-dmic-ef,
721 * because of the limitation that two devices cannot be enabled
722 * at the same time if they share the same backend.
723 */
724 for (i = 0; i < AUDIO_USECASE_MAX; i++)
725 switch_device[i] = false;
726
727 list_for_each(node, &adev->usecase_list) {
728 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800729 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700730 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700731 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700732 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
733 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700734 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
736 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700737 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700738 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 switch_device[usecase->id] = true;
740 num_uc_to_switch++;
741 }
742 }
743
744 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700745 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530747 /* Make sure the previous devices to be disabled first and then enable the
748 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749 list_for_each(node, &adev->usecase_list) {
750 usecase = node_to_item(node, struct audio_usecase, list);
751 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700752 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 }
754 }
755
756 list_for_each(node, &adev->usecase_list) {
757 usecase = node_to_item(node, struct audio_usecase, list);
758 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
762
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 /* Re-route all the usecases on the shared backend other than the
764 specified usecase to new snd devices */
765 list_for_each(node, &adev->usecase_list) {
766 usecase = node_to_item(node, struct audio_usecase, list);
767 /* Update the in_snd_device only before enabling the audio route */
768 if (switch_device[usecase->id] ) {
769 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800770 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530771 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 }
773 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 }
775}
776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700778static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700780 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700781 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782
783 switch (channels) {
784 /*
785 * Do not handle stereo output in Multi-channel cases
786 * Stereo case is handled in normal playback path
787 */
788 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700789 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800795 break;
796 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700797 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
799 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804 break;
805 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700806 ALOGE("HDMI does not support multi channel playback");
807 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 break;
809 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700810 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800811}
812
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800813audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
814 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815{
816 struct audio_usecase *usecase;
817 struct listnode *node;
818
819 list_for_each(node, &adev->usecase_list) {
820 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800821 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700822 ALOGV("%s: usecase id %d", __func__, usecase->id);
823 return usecase->id;
824 }
825 }
826 return USECASE_INVALID;
827}
828
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700829struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700830 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831{
832 struct audio_usecase *usecase;
833 struct listnode *node;
834
835 list_for_each(node, &adev->usecase_list) {
836 usecase = node_to_item(node, struct audio_usecase, list);
837 if (usecase->id == uc_id)
838 return usecase;
839 }
840 return NULL;
841}
842
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700843int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800845 snd_device_t out_snd_device = SND_DEVICE_NONE;
846 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 struct audio_usecase *usecase = NULL;
848 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800850 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800851 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase = get_usecase_from_list(adev, uc_id);
856 if (usecase == NULL) {
857 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
858 return -EINVAL;
859 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800861 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800862 (usecase->type == VOIP_CALL) ||
863 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700864 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800865 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 usecase->devices = usecase->stream.out->devices;
868 } else {
869 /*
870 * If the voice call is active, use the sound devices of voice call usecase
871 * so that it would not result any device switch. All the usecases will
872 * be switched to new device when select_devices() is called for voice call
873 * usecase. This is to avoid switching devices for voice call when
874 * check_usecases_codec_backend() is called below.
875 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700876 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700877 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800878 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700879 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
880 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 in_snd_device = vc_usecase->in_snd_device;
882 out_snd_device = vc_usecase->out_snd_device;
883 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800884 } else if (voice_extn_compress_voip_is_active(adev)) {
885 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700886 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530887 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700888 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800889 in_snd_device = voip_usecase->in_snd_device;
890 out_snd_device = voip_usecase->out_snd_device;
891 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800892 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800893 hfp_ucid = audio_extn_hfp_get_usecase();
894 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700895 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800896 in_snd_device = hfp_usecase->in_snd_device;
897 out_snd_device = hfp_usecase->out_snd_device;
898 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 if (usecase->type == PCM_PLAYBACK) {
901 usecase->devices = usecase->stream.out->devices;
902 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700904 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800905 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 if (usecase->stream.out == adev->primary_output &&
907 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800908 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 select_devices(adev, adev->active_input->usecase);
910 }
911 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 } else if (usecase->type == PCM_CAPTURE) {
913 usecase->devices = usecase->stream.in->device;
914 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700916 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530917 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
918 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
919 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
920 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700921 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700922 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
924 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700925 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700926 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700927 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 }
929 }
930
931 if (out_snd_device == usecase->out_snd_device &&
932 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 return 0;
934 }
935
sangwoobc677242013-08-08 16:53:43 +0900936 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700937 out_snd_device, platform_get_snd_device_name(out_snd_device),
938 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940 /*
941 * Limitation: While in call, to do a device switch we need to disable
942 * and enable both RX and TX devices though one of them is same as current
943 * device.
944 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700945 if ((usecase->type == VOICE_CALL) &&
946 (usecase->in_snd_device != SND_DEVICE_NONE) &&
947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700948 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700949 }
950
951 if (((usecase->type == VOICE_CALL) ||
952 (usecase->type == VOIP_CALL)) &&
953 (usecase->out_snd_device != SND_DEVICE_NONE)) {
954 /* Disable sidetone only if voice/voip call already exists */
955 if (voice_is_call_state_active(adev) ||
956 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700957 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 /* Disable current sound devices */
961 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_audio_route(adev, usecase);
963 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964 }
965
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 disable_audio_route(adev, usecase);
968 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969 }
970
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800971 /* Applicable only on the targets that has external modem.
972 * New device information should be sent to modem before enabling
973 * the devices to reduce in-call device switch time.
974 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700975 if ((usecase->type == VOICE_CALL) &&
976 (usecase->in_snd_device != SND_DEVICE_NONE) &&
977 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800978 status = platform_switch_voice_call_enable_device_config(adev->platform,
979 out_snd_device,
980 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700981 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800982
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 /* Enable new sound devices */
984 if (out_snd_device != SND_DEVICE_NONE) {
985 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
986 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700987 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988 }
989
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 if (in_snd_device != SND_DEVICE_NONE) {
991 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700992 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994
Avinash Vaish71a8b972014-07-24 15:36:33 +0530995 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700996 status = platform_switch_voice_call_device_post(adev->platform,
997 out_snd_device,
998 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530999 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001000 /* Enable sidetone only if voice/voip call already exists */
1001 if (voice_is_call_state_active(adev) ||
1002 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001003 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301004 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001005
sangwoo170731f2013-06-08 15:36:36 +09001006 usecase->in_snd_device = in_snd_device;
1007 usecase->out_snd_device = out_snd_device;
1008
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301009 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001010 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301011 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001012 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 usecase->stream.out->flags,
1014 usecase->stream.out->format,
1015 usecase->stream.out->sample_rate,
1016 usecase->stream.out->bit_width,
1017 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001018 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301019 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001020
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001022
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001023 /* Applicable only on the targets that has external modem.
1024 * Enable device command should be sent to modem only after
1025 * enabling voice call mixer controls
1026 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001027 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001028 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1029 out_snd_device,
1030 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301031 ALOGD("%s: done",__func__);
1032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 return status;
1034}
1035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036static int stop_input_stream(struct stream_in *in)
1037{
1038 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 struct audio_usecase *uc_info;
1040 struct audio_device *adev = in->dev;
1041
Eric Laurentc8400632013-02-14 19:04:54 -08001042 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Eric Laurent994a6932013-07-17 11:51:42 -07001044 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 uc_info = get_usecase_from_list(adev, in->usecase);
1047 if (uc_info == NULL) {
1048 ALOGE("%s: Could not find the usecase (%d) in the list",
1049 __func__, in->usecase);
1050 return -EINVAL;
1051 }
1052
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001053 /* Close in-call recording streams */
1054 voice_check_and_stop_incall_rec_usecase(adev, in);
1055
Eric Laurent150dbfe2013-02-27 14:31:02 -08001056 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001057 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058
1059 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001060 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001062 list_remove(&uc_info->list);
1063 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Eric Laurent994a6932013-07-17 11:51:42 -07001065 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 return ret;
1067}
1068
1069int start_input_stream(struct stream_in *in)
1070{
1071 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001072 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073 struct audio_usecase *uc_info;
1074 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301075 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076
Mingming Yin2664a5b2015-09-03 10:53:11 -07001077 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1078 if (get_usecase_from_list(adev, usecase) == NULL)
1079 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301080 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1081 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001082
Naresh Tanniru80659832014-06-04 18:17:56 +05301083
1084 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301085 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301086 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087 goto error_config;
1088 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001090 /* Check if source matches incall recording usecase criteria */
1091 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1092 if (ret)
1093 goto error_config;
1094 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001095 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1096
1097 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1098 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1099 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1100 goto error_config;
1101 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001102
Eric Laurentb23d5282013-05-14 15:27:20 -07001103 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 if (in->pcm_device_id < 0) {
1105 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1106 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001107 ret = -EINVAL;
1108 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110
1111 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001113
1114 if (!uc_info) {
1115 ret = -ENOMEM;
1116 goto error_config;
1117 }
1118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 uc_info->id = in->usecase;
1120 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001121 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 uc_info->devices = in->device;
1123 uc_info->in_snd_device = SND_DEVICE_NONE;
1124 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001126 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301127 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129
Eric Laurentc8400632013-02-14 19:04:54 -08001130 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001131 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1132
1133 unsigned int flags = PCM_IN;
1134 unsigned int pcm_open_retry_count = 0;
1135
1136 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1137 flags |= PCM_MMAP | PCM_NOIRQ;
1138 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1139 }
1140
1141 while (1) {
1142 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1143 flags, &in->config);
1144 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1145 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1146 if (in->pcm != NULL) {
1147 pcm_close(in->pcm);
1148 in->pcm = NULL;
1149 }
1150 if (pcm_open_retry_count-- == 0) {
1151 ret = -EIO;
1152 goto error_open;
1153 }
1154 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1155 continue;
1156 }
1157 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301159 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301160
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001161 ALOGV("%s: pcm_prepare start", __func__);
1162 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001163 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001164
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 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001632
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001633 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1634 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001635
1636 ALOGV("%s: pcm_prepare start", __func__);
1637 if (pcm_is_ready(out->pcm))
1638 pcm_prepare(out->pcm);
1639
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001640 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001641 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1642 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001644 out->compr = compress_open(adev->snd_card,
1645 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646 COMPRESS_IN, &out->compr_config);
1647 if (out->compr && !is_compress_ready(out->compr)) {
1648 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1649 compress_close(out->compr);
1650 out->compr = NULL;
1651 ret = -EIO;
1652 goto error_open;
1653 }
1654 if (out->offload_callback)
1655 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001656
Fred Oh3f43e742015-03-04 18:42:34 -08001657 /* Since small bufs uses blocking writes, a write will be blocked
1658 for the default max poll time (20s) in the event of an SSR.
1659 Reduce the poll time to observe and deal with SSR faster.
1660 */
1661 if (out->use_small_bufs) {
1662 compress_set_max_poll_wait(out->compr, 1000);
1663 }
1664
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001665 audio_extn_dts_create_state_notifier_node(out->usecase);
1666 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1667 popcount(out->channel_mask),
1668 out->playback_started);
1669
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001670#ifdef DS1_DOLBY_DDP_ENABLED
1671 if (audio_extn_is_dolby_format(out->format))
1672 audio_extn_dolby_send_ddp_endp_params(adev);
1673#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001674 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1675 if (adev->visualizer_start_output != NULL)
1676 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1677 if (adev->offload_effects_start_output != NULL)
1678 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001679 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001680 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001682
Eric Laurent994a6932013-07-17 11:51:42 -07001683 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001686error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001688error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001689 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690}
1691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692static int check_input_parameters(uint32_t sample_rate,
1693 audio_format_t format,
1694 int channel_count)
1695{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001696 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001698 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001699 !voice_extn_compress_voip_is_format_supported(format) &&
1700 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001701
1702 switch (channel_count) {
1703 case 1:
1704 case 2:
1705 case 6:
1706 break;
1707 default:
1708 ret = -EINVAL;
1709 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710
1711 switch (sample_rate) {
1712 case 8000:
1713 case 11025:
1714 case 12000:
1715 case 16000:
1716 case 22050:
1717 case 24000:
1718 case 32000:
1719 case 44100:
1720 case 48000:
1721 break;
1722 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001723 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724 }
1725
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001726 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727}
1728
1729static size_t get_input_buffer_size(uint32_t sample_rate,
1730 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001731 int channel_count,
1732 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733{
1734 size_t size = 0;
1735
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001736 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1737 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001739 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001740 if (is_low_latency)
1741 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001742 /* ToDo: should use frame_size computed based on the format and
1743 channel_count here. */
1744 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001746 /* make sure the size is multiple of 32 bytes
1747 * At 48 kHz mono 16-bit PCM:
1748 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1749 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1750 */
1751 size += 0x1f;
1752 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001753
1754 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755}
1756
1757static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1758{
1759 struct stream_out *out = (struct stream_out *)stream;
1760
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001761 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762}
1763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001764static int out_set_sample_rate(struct audio_stream *stream __unused,
1765 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766{
1767 return -ENOSYS;
1768}
1769
1770static size_t out_get_buffer_size(const struct audio_stream *stream)
1771{
1772 struct stream_out *out = (struct stream_out *)stream;
1773
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001774 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001776 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1777 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001779 return out->config.period_size *
1780 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781}
1782
1783static uint32_t out_get_channels(const struct audio_stream *stream)
1784{
1785 struct stream_out *out = (struct stream_out *)stream;
1786
1787 return out->channel_mask;
1788}
1789
1790static audio_format_t out_get_format(const struct audio_stream *stream)
1791{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 struct stream_out *out = (struct stream_out *)stream;
1793
1794 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795}
1796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001797static int out_set_format(struct audio_stream *stream __unused,
1798 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return -ENOSYS;
1801}
1802
1803static int out_standby(struct audio_stream *stream)
1804{
1805 struct stream_out *out = (struct stream_out *)stream;
1806 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301808 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1809 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001810 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1811 /* Ignore standby in case of voip call because the voip output
1812 * stream is closed in adev_close_output_stream()
1813 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301814 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001815 return 0;
1816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001818 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001820 if (adev->adm_deregister_stream)
1821 adev->adm_deregister_stream(adev->adm_data, out->handle);
1822
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001823 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001825 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001826 if (out->pcm) {
1827 pcm_close(out->pcm);
1828 out->pcm = NULL;
1829 }
1830 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001831 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001833 out->gapless_mdata.encoder_delay = 0;
1834 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 if (out->compr != NULL) {
1836 compress_close(out->compr);
1837 out->compr = NULL;
1838 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001841 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 }
1843 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001844 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 return 0;
1846}
1847
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001848static int out_dump(const struct audio_stream *stream __unused,
1849 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850{
1851 return 0;
1852}
1853
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1855{
1856 int ret = 0;
1857 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001858 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001859
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001861 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 return -EINVAL;
1863 }
1864
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301865 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001866
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001867 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1868 if(ret >= 0)
1869 is_meta_data_params = true;
1870 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301871 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001872 is_meta_data_params = true;
1873 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301874 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001875 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001876 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1877 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001878 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301879 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001880 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001881 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1882 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001883 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301884 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001885 }
1886
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001887 if(!is_meta_data_params) {
1888 ALOGV("%s: Not gapless meta data params", __func__);
1889 return 0;
1890 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891 out->send_new_metadata = 1;
1892 ALOGV("%s new encoder delay %u and padding %u", __func__,
1893 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1894
1895 return 0;
1896}
1897
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001898static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1899{
1900 return out == adev->primary_output || out == adev->voice_tx_output;
1901}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1904{
1905 struct stream_out *out = (struct stream_out *)stream;
1906 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001907 struct audio_usecase *usecase;
1908 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 struct str_parms *parms;
1910 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001911 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001912 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913
sangwoobc677242013-08-08 16:53:43 +09001914 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001915 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301917 if (!parms)
1918 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001919 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1920 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001923 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301926 * When HDMI cable is unplugged/usb hs is disconnected the
1927 * music playback is paused and the policy manager sends routing=0
1928 * But the audioflingercontinues to write data until standby time
1929 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930 * Avoid this by routing audio to speaker until standby.
1931 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301932 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1933 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001934 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001935 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1936 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001937 }
1938
1939 /*
1940 * select_devices() call below switches all the usecases on the same
1941 * backend to the new device. Refer to check_usecases_codec_backend() in
1942 * the select_devices(). But how do we undo this?
1943 *
1944 * For example, music playback is active on headset (deep-buffer usecase)
1945 * and if we go to ringtones and select a ringtone, low-latency usecase
1946 * will be started on headset+speaker. As we can't enable headset+speaker
1947 * and headset devices at the same time, select_devices() switches the music
1948 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1949 * So when the ringtone playback is completed, how do we undo the same?
1950 *
1951 * We are relying on the out_set_parameters() call on deep-buffer output,
1952 * once the ringtone playback is ended.
1953 * NOTE: We should not check if the current devices are same as new devices.
1954 * Because select_devices() must be called to switch back the music
1955 * playback to headset.
1956 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001957 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001958 out->devices = val;
1959
1960 if (!out->standby)
1961 select_devices(adev, out->usecase);
1962
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001963 if (output_drives_call(adev, out)) {
1964 if(!voice_is_in_call(adev)) {
1965 if (adev->mode == AUDIO_MODE_IN_CALL) {
1966 adev->current_call_output = out;
1967 ret = voice_start_call(adev);
1968 }
1969 } else {
1970 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001971 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001972 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001973 }
1974 }
1975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001977 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001979
1980 if (out == adev->primary_output) {
1981 pthread_mutex_lock(&adev->lock);
1982 audio_extn_set_parameters(adev, parms);
1983 pthread_mutex_unlock(&adev->lock);
1984 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001985 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001986 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001987 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001988
1989 audio_extn_dts_create_state_notifier_node(out->usecase);
1990 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1991 popcount(out->channel_mask),
1992 out->playback_started);
1993
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001994 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001995 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301998error:
Eric Laurent994a6932013-07-17 11:51:42 -07001999 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 return ret;
2001}
2002
2003static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2004{
2005 struct stream_out *out = (struct stream_out *)stream;
2006 struct str_parms *query = str_parms_create_str(keys);
2007 char *str;
2008 char value[256];
2009 struct str_parms *reply = str_parms_create();
2010 size_t i, j;
2011 int ret;
2012 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002013
2014 if (!query || !reply) {
2015 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2016 return NULL;
2017 }
2018
Eric Laurent994a6932013-07-17 11:51:42 -07002019 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2021 if (ret >= 0) {
2022 value[0] = '\0';
2023 i = 0;
2024 while (out->supported_channel_masks[i] != 0) {
2025 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2026 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2027 if (!first) {
2028 strcat(value, "|");
2029 }
2030 strcat(value, out_channels_name_to_enum_table[j].name);
2031 first = false;
2032 break;
2033 }
2034 }
2035 i++;
2036 }
2037 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2038 str = str_parms_to_str(reply);
2039 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002040 voice_extn_out_get_parameters(out, query, reply);
2041 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002042 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002043 free(str);
2044 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002045 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002047
2048 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2049 if (ret >= 0) {
2050 value[0] = '\0';
2051 i = 0;
2052 first = true;
2053 while (out->supported_formats[i] != 0) {
2054 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2055 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2056 if (!first) {
2057 strcat(value, "|");
2058 }
2059 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2060 first = false;
2061 break;
2062 }
2063 }
2064 i++;
2065 }
2066 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2067 str = str_parms_to_str(reply);
2068 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 str_parms_destroy(query);
2070 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002071 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 return str;
2073}
2074
2075static uint32_t out_get_latency(const struct audio_stream_out *stream)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002078 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079
Alexy Josephaa54c872014-12-03 02:46:47 -08002080 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002081 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002082 } else {
2083 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002085 }
2086
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302087 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002088 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089}
2090
2091static int out_set_volume(struct audio_stream_out *stream, float left,
2092 float right)
2093{
Eric Laurenta9024de2013-04-04 09:19:12 -07002094 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 int volume[2];
2096
Eric Laurenta9024de2013-04-04 09:19:12 -07002097 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2098 /* only take left channel into account: the API is for stereo anyway */
2099 out->muted = (left == 0.0f);
2100 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002101 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002102 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2103 /*
2104 * Set mute or umute on HDMI passthrough stream.
2105 * Only take left channel into account.
2106 * Mute is 0 and unmute 1
2107 */
2108 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2109 } else {
2110 char mixer_ctl_name[128];
2111 struct audio_device *adev = out->dev;
2112 struct mixer_ctl *ctl;
2113 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002114 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002116 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2117 "Compress Playback %d Volume", pcm_device_id);
2118 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2119 if (!ctl) {
2120 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2121 __func__, mixer_ctl_name);
2122 return -EINVAL;
2123 }
2124 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2125 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2126 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2127 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002129 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 return -ENOSYS;
2132}
2133
2134static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2135 size_t bytes)
2136{
2137 struct stream_out *out = (struct stream_out *)stream;
2138 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002140 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302143
Naresh Tanniru80659832014-06-04 18:17:56 +05302144 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002145 // increase written size during SSR to avoid mismatch
2146 // with the written frames count in AF
2147 if (!is_offload_usecase(out->usecase))
2148 out->written += bytes / (out->config.channels * sizeof(short));
2149
Naresh Tanniru80659832014-06-04 18:17:56 +05302150 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302151 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302152 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302153 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002154 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302155 //during SSR for compress usecase we should return error to flinger
2156 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2157 pthread_mutex_unlock(&out->lock);
2158 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302159 }
2160 }
2161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002163 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002164 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002165 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2166 ret = voice_extn_compress_voip_start_output_stream(out);
2167 else
2168 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002169 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002170 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002172 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 goto exit;
2174 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002175 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2176 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002179 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002180 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002181 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002182 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002183 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2184 out->send_new_metadata = 0;
2185 }
2186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302188 if (ret < 0)
2189 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002190 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002191 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302192 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302194 } else if (-ENETRESET == ret) {
2195 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2196 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2197 pthread_mutex_unlock(&out->lock);
2198 out_standby(&out->stream.common);
2199 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302201 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002203 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 out->playback_started = 1;
2205 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002206
2207 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2208 popcount(out->channel_mask),
2209 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 }
2211 pthread_mutex_unlock(&out->lock);
2212 return ret;
2213 } else {
2214 if (out->pcm) {
2215 if (out->muted)
2216 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002217
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002219
2220 if (adev->adm_request_focus)
2221 adev->adm_request_focus(adev->adm_data, out->handle);
2222
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002223 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2224 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2225 else
2226 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002227
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302228 if (ret < 0)
2229 ret = -errno;
2230 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002231 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002232
2233 if (adev->adm_abandon_focus)
2234 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 }
2237
2238exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302239 /* ToDo: There may be a corner case when SSR happens back to back during
2240 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302241 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302242 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302243 }
2244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 pthread_mutex_unlock(&out->lock);
2246
2247 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002248 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002249 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302250 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302251 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302252 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302253 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302254 out->standby = true;
2255 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002257 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302258 out_get_sample_rate(&out->stream.common));
2259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 }
2261 return bytes;
2262}
2263
2264static int out_get_render_position(const struct audio_stream_out *stream,
2265 uint32_t *dsp_frames)
2266{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302268 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002269
2270 if (dsp_frames == NULL)
2271 return -EINVAL;
2272
2273 *dsp_frames = 0;
2274 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002275 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 pthread_mutex_lock(&out->lock);
2277 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302278 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302280 if (ret < 0)
2281 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 ALOGVV("%s rendered frames %d sample_rate %d",
2283 __func__, *dsp_frames, out->sample_rate);
2284 }
2285 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302286 if (-ENETRESET == ret) {
2287 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2288 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2289 return -EINVAL;
2290 } else if(ret < 0) {
2291 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2292 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302293 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2294 /*
2295 * Handle corner case where compress session is closed during SSR
2296 * and timestamp is queried
2297 */
2298 ALOGE(" ERROR: sound card not active, return error");
2299 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302300 } else {
2301 return 0;
2302 }
Zhou Song32a556e2015-05-05 10:46:56 +08002303 } else if (audio_is_linear_pcm(out->format)) {
2304 *dsp_frames = out->written;
2305 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 } else
2307 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308}
2309
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002310static int out_add_audio_effect(const struct audio_stream *stream __unused,
2311 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312{
2313 return 0;
2314}
2315
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002316static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2317 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318{
2319 return 0;
2320}
2321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002322static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2323 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324{
2325 return -EINVAL;
2326}
2327
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002328static int out_get_presentation_position(const struct audio_stream_out *stream,
2329 uint64_t *frames, struct timespec *timestamp)
2330{
2331 struct stream_out *out = (struct stream_out *)stream;
2332 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002333 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002334
2335 pthread_mutex_lock(&out->lock);
2336
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002337 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002338 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302339 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002340 &out->sample_rate);
2341 ALOGVV("%s rendered frames %ld sample_rate %d",
2342 __func__, dsp_frames, out->sample_rate);
2343 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302344 if (ret < 0)
2345 ret = -errno;
2346 if (-ENETRESET == ret) {
2347 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2348 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2349 ret = -EINVAL;
2350 } else
2351 ret = 0;
2352
Eric Laurent949a0892013-09-20 09:20:13 -07002353 /* this is the best we can do */
2354 clock_gettime(CLOCK_MONOTONIC, timestamp);
2355 }
2356 } else {
2357 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002358 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002359 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2360 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002361 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002362 // This adjustment accounts for buffering after app processor.
2363 // It is based on estimated DSP latency per use case, rather than exact.
2364 signed_frames -=
2365 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2366
Eric Laurent949a0892013-09-20 09:20:13 -07002367 // It would be unusual for this value to be negative, but check just in case ...
2368 if (signed_frames >= 0) {
2369 *frames = signed_frames;
2370 ret = 0;
2371 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002372 }
2373 }
2374 }
2375
2376 pthread_mutex_unlock(&out->lock);
2377
2378 return ret;
2379}
2380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381static int out_set_callback(struct audio_stream_out *stream,
2382 stream_callback_t callback, void *cookie)
2383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385
2386 ALOGV("%s", __func__);
2387 pthread_mutex_lock(&out->lock);
2388 out->offload_callback = callback;
2389 out->offload_cookie = cookie;
2390 pthread_mutex_unlock(&out->lock);
2391 return 0;
2392}
2393
2394static int out_pause(struct audio_stream_out* stream)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 int status = -ENOSYS;
2398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002400 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 pthread_mutex_lock(&out->lock);
2402 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302403 struct audio_device *adev = out->dev;
2404 int snd_scard_state = get_snd_card_state(adev);
2405
2406 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2407 status = compress_pause(out->compr);
2408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002410
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302411 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002412 audio_extn_dts_notify_playback_state(out->usecase, 0,
2413 out->sample_rate, popcount(out->channel_mask),
2414 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 }
2416 pthread_mutex_unlock(&out->lock);
2417 }
2418 return status;
2419}
2420
2421static int out_resume(struct audio_stream_out* stream)
2422{
2423 struct stream_out *out = (struct stream_out *)stream;
2424 int status = -ENOSYS;
2425 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002426 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002427 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 status = 0;
2429 pthread_mutex_lock(&out->lock);
2430 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302431 struct audio_device *adev = out->dev;
2432 int snd_scard_state = get_snd_card_state(adev);
2433
2434 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2435 status = compress_resume(out->compr);
2436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002438
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302439 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002440 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2441 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 }
2443 pthread_mutex_unlock(&out->lock);
2444 }
2445 return status;
2446}
2447
2448static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2449{
2450 struct stream_out *out = (struct stream_out *)stream;
2451 int status = -ENOSYS;
2452 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002453 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 pthread_mutex_lock(&out->lock);
2455 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2456 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2457 else
2458 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2459 pthread_mutex_unlock(&out->lock);
2460 }
2461 return status;
2462}
2463
2464static int out_flush(struct audio_stream_out* stream)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002468 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002469 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 pthread_mutex_lock(&out->lock);
2471 stop_compressed_output_l(out);
2472 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002473 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 return 0;
2475 }
2476 return -ENOSYS;
2477}
2478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479/** audio_stream_in implementation **/
2480static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2481{
2482 struct stream_in *in = (struct stream_in *)stream;
2483
2484 return in->config.rate;
2485}
2486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002487static int in_set_sample_rate(struct audio_stream *stream __unused,
2488 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489{
2490 return -ENOSYS;
2491}
2492
2493static size_t in_get_buffer_size(const struct audio_stream *stream)
2494{
2495 struct stream_in *in = (struct stream_in *)stream;
2496
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002497 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2498 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002499 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2500 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002501
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002502 return in->config.period_size *
2503 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504}
2505
2506static uint32_t in_get_channels(const struct audio_stream *stream)
2507{
2508 struct stream_in *in = (struct stream_in *)stream;
2509
2510 return in->channel_mask;
2511}
2512
2513static audio_format_t in_get_format(const struct audio_stream *stream)
2514{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002515 struct stream_in *in = (struct stream_in *)stream;
2516
2517 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518}
2519
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002520static int in_set_format(struct audio_stream *stream __unused,
2521 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522{
2523 return -ENOSYS;
2524}
2525
2526static int in_standby(struct audio_stream *stream)
2527{
2528 struct stream_in *in = (struct stream_in *)stream;
2529 struct audio_device *adev = in->dev;
2530 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302531 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2532 stream, in->usecase, use_case_table[in->usecase]);
2533
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002534 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2535 /* Ignore standby in case of voip call because the voip input
2536 * stream is closed in adev_close_input_stream()
2537 */
2538 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2539 return status;
2540 }
2541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002543 if (!in->standby && in->is_st_session) {
2544 ALOGD("%s: sound trigger pcm stop lab", __func__);
2545 audio_extn_sound_trigger_stop_lab(in);
2546 in->standby = 1;
2547 }
2548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002550 if (adev->adm_deregister_stream)
2551 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2552
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002553 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 if (in->pcm) {
2556 pcm_close(in->pcm);
2557 in->pcm = NULL;
2558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 }
2562 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002563 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 return status;
2565}
2566
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002567static int in_dump(const struct audio_stream *stream __unused,
2568 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569{
2570 return 0;
2571}
2572
2573static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2574{
2575 struct stream_in *in = (struct stream_in *)stream;
2576 struct audio_device *adev = in->dev;
2577 struct str_parms *parms;
2578 char *str;
2579 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002580 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302582 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 parms = str_parms_create_str(kvpairs);
2584
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302585 if (!parms)
2586 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002588 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002589
2590 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2591 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 val = atoi(value);
2593 /* no audio source uses val == 0 */
2594 if ((in->source != val) && (val != 0)) {
2595 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002596 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2597 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2598 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2599 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002600 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002601 err = voice_extn_compress_voip_open_input_stream(in);
2602 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002603 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002604 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002605 }
2606 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 }
2608 }
2609
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002610 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2611 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002613 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 in->device = val;
2615 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002616 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002617 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 }
2619 }
2620
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002621done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002623 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624
2625 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302626error:
Eric Laurent994a6932013-07-17 11:51:42 -07002627 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 return ret;
2629}
2630
2631static char* in_get_parameters(const struct audio_stream *stream,
2632 const char *keys)
2633{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002634 struct stream_in *in = (struct stream_in *)stream;
2635 struct str_parms *query = str_parms_create_str(keys);
2636 char *str;
2637 char value[256];
2638 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002639
2640 if (!query || !reply) {
2641 ALOGE("in_get_parameters: failed to create query or reply");
2642 return NULL;
2643 }
2644
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002645 ALOGV("%s: enter: keys - %s", __func__, keys);
2646
2647 voice_extn_in_get_parameters(in, query, reply);
2648
2649 str = str_parms_to_str(reply);
2650 str_parms_destroy(query);
2651 str_parms_destroy(reply);
2652
2653 ALOGV("%s: exit: returns - %s", __func__, str);
2654 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655}
2656
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002657static int in_set_gain(struct audio_stream_in *stream __unused,
2658 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659{
2660 return 0;
2661}
2662
2663static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2664 size_t bytes)
2665{
2666 struct stream_in *in = (struct stream_in *)stream;
2667 struct audio_device *adev = in->dev;
2668 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302669 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302672
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002673 if (in->is_st_session) {
2674 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2675 /* Read from sound trigger HAL */
2676 audio_extn_sound_trigger_read(in, buffer, bytes);
2677 pthread_mutex_unlock(&in->lock);
2678 return bytes;
2679 }
2680
2681 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2682 ALOGD(" %s: sound card is not active/SSR state", __func__);
2683 ret= -EIO;;
2684 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302685 }
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002688 pthread_mutex_lock(&adev->lock);
2689 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2690 ret = voice_extn_compress_voip_start_input_stream(in);
2691 else
2692 ret = start_input_stream(in);
2693 pthread_mutex_unlock(&adev->lock);
2694 if (ret != 0) {
2695 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 }
2697 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002698 if (adev->adm_register_input_stream)
2699 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002702 if (adev->adm_request_focus)
2703 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002706 if (audio_extn_ssr_get_enabled() &&
2707 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002708 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002709 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2710 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002711 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2712 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002713 else
2714 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302715 if (ret < 0)
2716 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 }
2718
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002719 if (adev->adm_abandon_focus)
2720 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 /*
2723 * Instead of writing zeroes here, we could trust the hardware
2724 * to always provide zeroes when muted.
2725 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302726 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2727 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 memset(buffer, 0, bytes);
2729
2730exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302731 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302732 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002733 if (-ENETRESET == ret)
2734 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 pthread_mutex_unlock(&in->lock);
2737
2738 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302739 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302740 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302741 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302742 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302743 in->standby = true;
2744 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302745 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002747 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002748 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302749 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 }
2751 return bytes;
2752}
2753
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002754static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002759static int add_remove_audio_effect(const struct audio_stream *stream,
2760 effect_handle_t effect,
2761 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002763 struct stream_in *in = (struct stream_in *)stream;
2764 int status = 0;
2765 effect_descriptor_t desc;
2766
2767 status = (*effect)->get_descriptor(effect, &desc);
2768 if (status != 0)
2769 return status;
2770
2771 pthread_mutex_lock(&in->lock);
2772 pthread_mutex_lock(&in->dev->lock);
2773 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2774 in->enable_aec != enable &&
2775 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2776 in->enable_aec = enable;
2777 if (!in->standby)
2778 select_devices(in->dev, in->usecase);
2779 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002780 if (in->enable_ns != enable &&
2781 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2782 in->enable_ns = enable;
2783 if (!in->standby)
2784 select_devices(in->dev, in->usecase);
2785 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002786 pthread_mutex_unlock(&in->dev->lock);
2787 pthread_mutex_unlock(&in->lock);
2788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 return 0;
2790}
2791
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002792static int in_add_audio_effect(const struct audio_stream *stream,
2793 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794{
Eric Laurent994a6932013-07-17 11:51:42 -07002795 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002796 return add_remove_audio_effect(stream, effect, true);
2797}
2798
2799static int in_remove_audio_effect(const struct audio_stream *stream,
2800 effect_handle_t effect)
2801{
Eric Laurent994a6932013-07-17 11:51:42 -07002802 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002803 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804}
2805
2806static int adev_open_output_stream(struct audio_hw_device *dev,
2807 audio_io_handle_t handle,
2808 audio_devices_t devices,
2809 audio_output_flags_t flags,
2810 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002811 struct audio_stream_out **stream_out,
2812 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813{
2814 struct audio_device *adev = (struct audio_device *)dev;
2815 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002816 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002817 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302820
2821 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2822 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002823 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302824 return -EINVAL;
2825 }
2826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2828
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302829 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2830 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2831 devices, flags, &out->stream);
2832
2833
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002834 if (!out) {
2835 return -ENOMEM;
2836 }
2837
Haynes Mathew George204045b2015-02-25 20:32:03 -08002838 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2839 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841 if (devices == AUDIO_DEVICE_NONE)
2842 devices = AUDIO_DEVICE_OUT_SPEAKER;
2843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 out->flags = flags;
2845 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002846 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002847 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 out->sample_rate = config->sample_rate;
2849 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2850 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002851 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002852 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002853 out->non_blocking = 0;
2854 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855
2856 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002857 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2858 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002859 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2860 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2861
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002862 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002863 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2864 ret = read_hdmi_channel_masks(out);
2865
2866 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2867 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002868 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002869 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002870 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002871
2872 if (config->sample_rate == 0)
2873 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2874 if (config->channel_mask == 0)
2875 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2876
2877 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2880 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002882 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002884 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2885 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002886 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002887 ret = voice_extn_compress_voip_open_output_stream(out);
2888 if (ret != 0) {
2889 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2890 __func__, ret);
2891 goto error_open;
2892 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002893 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2894 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2895
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2897 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2898 ALOGE("%s: Unsupported Offload information", __func__);
2899 ret = -EINVAL;
2900 goto error_open;
2901 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902
2903 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2904 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2905 ALOGV("read and update_pass through formats");
2906 ret = audio_extn_dolby_update_passt_formats(adev, out);
2907 if(ret != 0) {
2908 goto error_open;
2909 }
2910 if(config->offload_info.format == 0)
2911 config->offload_info.format = out->supported_formats[0];
2912 }
2913
Mingming Yin90310102013-11-13 16:57:00 -08002914 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002915 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002916 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 ret = -EINVAL;
2918 goto error_open;
2919 }
2920
2921 out->compr_config.codec = (struct snd_codec *)
2922 calloc(1, sizeof(struct snd_codec));
2923
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002924 if (!out->compr_config.codec) {
2925 ret = -ENOMEM;
2926 goto error_open;
2927 }
2928
vivek mehta0ea887a2015-08-26 14:01:20 -07002929 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2930 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2931 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2932 } else {
2933 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2934 out->usecase = get_offload_usecase(adev);
2935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 if (config->offload_info.channel_mask)
2937 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002938 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002940 config->offload_info.channel_mask = config->channel_mask;
2941 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002942 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 out->sample_rate = config->offload_info.sample_rate;
2944
2945 out->stream.set_callback = out_set_callback;
2946 out->stream.pause = out_pause;
2947 out->stream.resume = out_resume;
2948 out->stream.drain = out_drain;
2949 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002950 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002952 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002953 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002954 audio_extn_dolby_get_snd_codec_id(adev, out,
2955 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002956 else
2957 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002959
2960 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2961 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002962 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002963 platform_get_pcm_offload_buffer_size(&config->offload_info);
2964 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2965 out->compr_config.fragment_size =
2966 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002967 } else {
2968 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002969 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002970 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2972 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002973 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002974 out->compr_config.codec->bit_rate =
2975 config->offload_info.bit_rate;
2976 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002977 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302979 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002980 /*TODO: Do we need to change it for passthrough */
2981 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982
Manish Dewangana6fc5442015-08-24 20:30:31 +05302983 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2984 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2985 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2986 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002987 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2988 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002989 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002990 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002991 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2992 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002993
Mingming Yin3ee55c62014-08-04 14:23:35 -07002994 if (out->bit_width == 24) {
2995 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2996 }
2997
Amit Shekhar6f461b12014-08-01 14:52:58 -07002998 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302999 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3002 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003003
Mingming Yin497419f2015-07-01 16:57:32 -07003004 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003005 //this flag is set from framework only if its for PCM formats
3006 //no need to check for PCM format again
3007 out->non_blocking = 0;
3008 out->use_small_bufs = true;
3009 ALOGI("Keep write blocking for small buff: non_blockling %d",
3010 out->non_blocking);
3011 }
3012
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003013 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003014 out->offload_state = OFFLOAD_STATE_IDLE;
3015 out->playback_started = 0;
3016
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003017 audio_extn_dts_create_state_notifier_node(out->usecase);
3018
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003019 create_offload_callback_thread(out);
3020 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3021 __func__, config->offload_info.version,
3022 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003023 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003024 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003025 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3026 ret = voice_check_and_set_incall_music_usecase(adev, out);
3027 if (ret != 0) {
3028 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3029 __func__, ret);
3030 goto error_open;
3031 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003032 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3033 if (config->sample_rate == 0)
3034 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3035 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3036 config->sample_rate != 8000) {
3037 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3038 ret = -EINVAL;
3039 goto error_open;
3040 }
3041 out->sample_rate = config->sample_rate;
3042 out->config.rate = config->sample_rate;
3043 if (config->format == AUDIO_FORMAT_DEFAULT)
3044 config->format = AUDIO_FORMAT_PCM_16_BIT;
3045 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3046 config->format = AUDIO_FORMAT_PCM_16_BIT;
3047 ret = -EINVAL;
3048 goto error_open;
3049 }
3050 out->format = config->format;
3051 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3052 out->config = pcm_config_afe_proxy_playback;
3053 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003054 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3055 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3056 out->config = pcm_config_low_latency;
3057 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003058 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003059 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3061 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003063 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3064 format = AUDIO_FORMAT_PCM_16_BIT;
3065 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3066 out->config = pcm_config_deep_buffer;
3067 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003068 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003069 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003070 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003071 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003072 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003073 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 }
3075
Amit Shekhar1d896042014-10-03 13:16:09 -07003076 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3077 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003078 /* TODO remove this hardcoding and check why width is zero*/
3079 if (out->bit_width == 0)
3080 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003081 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3082 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003083 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003084 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003085 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3086 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3087 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003088 if(adev->primary_output == NULL)
3089 adev->primary_output = out;
3090 else {
3091 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003092 ret = -EEXIST;
3093 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003094 }
3095 }
3096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 /* Check if this usecase is already existing */
3098 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003099 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3100 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003103 ret = -EEXIST;
3104 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 }
3106 pthread_mutex_unlock(&adev->lock);
3107
3108 out->stream.common.get_sample_rate = out_get_sample_rate;
3109 out->stream.common.set_sample_rate = out_set_sample_rate;
3110 out->stream.common.get_buffer_size = out_get_buffer_size;
3111 out->stream.common.get_channels = out_get_channels;
3112 out->stream.common.get_format = out_get_format;
3113 out->stream.common.set_format = out_set_format;
3114 out->stream.common.standby = out_standby;
3115 out->stream.common.dump = out_dump;
3116 out->stream.common.set_parameters = out_set_parameters;
3117 out->stream.common.get_parameters = out_get_parameters;
3118 out->stream.common.add_audio_effect = out_add_audio_effect;
3119 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3120 out->stream.get_latency = out_get_latency;
3121 out->stream.set_volume = out_set_volume;
3122 out->stream.write = out_write;
3123 out->stream.get_render_position = out_get_render_position;
3124 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003125 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003128 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003129 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
3131 config->format = out->stream.common.get_format(&out->stream.common);
3132 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3133 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3134
3135 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303136 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003137 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003138
3139 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3140 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3141 popcount(out->channel_mask), out->playback_started);
3142
Eric Laurent994a6932013-07-17 11:51:42 -07003143 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003145
3146error_open:
3147 free(out);
3148 *stream_out = NULL;
3149 ALOGD("%s: exit: ret %d", __func__, ret);
3150 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151}
3152
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003153static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 struct audio_stream_out *stream)
3155{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156 struct stream_out *out = (struct stream_out *)stream;
3157 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003158 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303160 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3161
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003162 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303163 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003164 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303165 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003166 if(ret != 0)
3167 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3168 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003169 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003170 out_standby(&stream->common);
3171
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003172 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003173 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003175 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003176 if (out->compr_config.codec != NULL)
3177 free(out->compr_config.codec);
3178 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003179
3180 if (adev->voice_tx_output == out)
3181 adev->voice_tx_output = NULL;
3182
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183 pthread_cond_destroy(&out->cond);
3184 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003186 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187}
3188
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003189static void close_compress_sessions(struct audio_device *adev)
3190{
Mingming Yin7b762e72015-03-04 13:47:32 -08003191 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303192 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003193 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003194 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303195
3196 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003197 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303198 if (is_offload_usecase(usecase->id)) {
3199 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003200 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3201 out = usecase->stream.out;
3202 pthread_mutex_unlock(&adev->lock);
3203 out_standby(&out->stream.common);
3204 pthread_mutex_lock(&adev->lock);
3205 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303206 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003207 }
3208 pthread_mutex_unlock(&adev->lock);
3209}
3210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3212{
3213 struct audio_device *adev = (struct audio_device *)dev;
3214 struct str_parms *parms;
3215 char *str;
3216 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003217 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003218 int ret;
3219 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003221 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303224 if (!parms)
3225 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003226 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3227 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303228 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303229 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303230 struct listnode *node;
3231 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303232 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303233 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003234 //close compress sessions on OFFLINE status
3235 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303236 } else if (strstr(snd_card_status, "ONLINE")) {
3237 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303238 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003239 //send dts hpx license if enabled
3240 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303241 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303242 }
3243
3244 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003245 status = voice_set_parameters(adev, parms);
3246 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003247 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003249 status = platform_set_parameters(adev->platform, parms);
3250 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003251 goto done;
3252
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3254 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003255 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3257 adev->bluetooth_nrec = true;
3258 else
3259 adev->bluetooth_nrec = false;
3260 }
3261
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003262 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3263 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3265 adev->screen_off = false;
3266 else
3267 adev->screen_off = true;
3268 }
3269
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003270 ret = str_parms_get_int(parms, "rotation", &val);
3271 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003272 bool reverse_speakers = false;
3273 switch(val) {
3274 // FIXME: note that the code below assumes that the speakers are in the correct placement
3275 // relative to the user when the device is rotated 90deg from its default rotation. This
3276 // assumption is device-specific, not platform-specific like this code.
3277 case 270:
3278 reverse_speakers = true;
3279 break;
3280 case 0:
3281 case 90:
3282 case 180:
3283 break;
3284 default:
3285 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003286 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003287 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003288 if (status == 0) {
3289 if (adev->speaker_lr_swap != reverse_speakers) {
3290 adev->speaker_lr_swap = reverse_speakers;
3291 // only update the selected device if there is active pcm playback
3292 struct audio_usecase *usecase;
3293 struct listnode *node;
3294 list_for_each(node, &adev->usecase_list) {
3295 usecase = node_to_item(node, struct audio_usecase, list);
3296 if (usecase->type == PCM_PLAYBACK) {
3297 select_devices(adev, usecase->id);
3298 break;
3299 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003300 }
3301 }
3302 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003303 }
3304
Mingming Yin514a8bc2014-07-29 15:22:21 -07003305 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3306 if (ret >= 0) {
3307 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3308 adev->bt_wb_speech_enabled = true;
3309 else
3310 adev->bt_wb_speech_enabled = false;
3311 }
3312
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003313 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3314 if (ret >= 0) {
3315 val = atoi(value);
3316 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3317 ALOGV("cache new edid");
3318 platform_cache_edid(adev->platform);
3319 }
3320 }
3321
3322 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3323 if (ret >= 0) {
3324 val = atoi(value);
3325 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3326 ALOGV("invalidate cached edid");
3327 platform_invalidate_edid(adev->platform);
3328 }
3329 }
3330
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003331 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003332
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003333done:
3334 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003335 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303336error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003337 ALOGV("%s: exit with code(%d)", __func__, status);
3338 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339}
3340
3341static char* adev_get_parameters(const struct audio_hw_device *dev,
3342 const char *keys)
3343{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003344 struct audio_device *adev = (struct audio_device *)dev;
3345 struct str_parms *reply = str_parms_create();
3346 struct str_parms *query = str_parms_create_str(keys);
3347 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303348 char value[256] = {0};
3349 int ret = 0;
3350
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003351 if (!query || !reply) {
3352 ALOGE("adev_get_parameters: failed to create query or reply");
3353 return NULL;
3354 }
3355
Naresh Tannirud7205b62014-06-20 02:54:48 +05303356 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3357 sizeof(value));
3358 if (ret >=0) {
3359 int val = 1;
3360 pthread_mutex_lock(&adev->snd_card_status.lock);
3361 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3362 val = 0;
3363 pthread_mutex_unlock(&adev->snd_card_status.lock);
3364 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3365 goto exit;
3366 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003367
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003368 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003369 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003370 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003371 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303372 pthread_mutex_unlock(&adev->lock);
3373
Naresh Tannirud7205b62014-06-20 02:54:48 +05303374exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003375 str = str_parms_to_str(reply);
3376 str_parms_destroy(query);
3377 str_parms_destroy(reply);
3378
3379 ALOGV("%s: exit: returns - %s", __func__, str);
3380 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003383static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384{
3385 return 0;
3386}
3387
3388static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3389{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003390 int ret;
3391 struct audio_device *adev = (struct audio_device *)dev;
3392 pthread_mutex_lock(&adev->lock);
3393 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003394 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003395 pthread_mutex_unlock(&adev->lock);
3396 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397}
3398
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003399static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3400 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401{
3402 return -ENOSYS;
3403}
3404
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003405static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3406 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
3408 return -ENOSYS;
3409}
3410
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003411static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3412 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413{
3414 return -ENOSYS;
3415}
3416
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003417static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3418 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419{
3420 return -ENOSYS;
3421}
3422
3423static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3424{
3425 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 pthread_mutex_lock(&adev->lock);
3428 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003429 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003431 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3432 voice_is_in_call(adev)) {
3433 voice_stop_call(adev);
3434 adev->current_call_output = NULL;
3435 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 }
3437 pthread_mutex_unlock(&adev->lock);
3438 return 0;
3439}
3440
3441static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3442{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003443 int ret;
3444
3445 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003446 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003447 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3448 pthread_mutex_unlock(&adev->lock);
3449
3450 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451}
3452
3453static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3454{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003455 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 return 0;
3457}
3458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003459static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 const struct audio_config *config)
3461{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003462 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003464 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3465 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466}
3467
3468static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003469 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 audio_devices_t devices,
3471 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003472 struct audio_stream_in **stream_in,
3473 audio_input_flags_t flags __unused,
3474 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003475 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476{
3477 struct audio_device *adev = (struct audio_device *)dev;
3478 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003480 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003481 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 *stream_in = NULL;
3484 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3485 return -EINVAL;
3486
3487 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003488
3489 if (!in) {
3490 ALOGE("failed to allocate input stream");
3491 return -ENOMEM;
3492 }
3493
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303494 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003495 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3496 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003498 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 in->stream.common.get_sample_rate = in_get_sample_rate;
3501 in->stream.common.set_sample_rate = in_set_sample_rate;
3502 in->stream.common.get_buffer_size = in_get_buffer_size;
3503 in->stream.common.get_channels = in_get_channels;
3504 in->stream.common.get_format = in_get_format;
3505 in->stream.common.set_format = in_set_format;
3506 in->stream.common.standby = in_standby;
3507 in->stream.common.dump = in_dump;
3508 in->stream.common.set_parameters = in_set_parameters;
3509 in->stream.common.get_parameters = in_get_parameters;
3510 in->stream.common.add_audio_effect = in_add_audio_effect;
3511 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3512 in->stream.set_gain = in_set_gain;
3513 in->stream.read = in_read;
3514 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3515
3516 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003517 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 in->standby = 1;
3520 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003521 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003522 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
3524 /* Update config params with the requested sample rate and channels */
3525 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003526 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3527 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3528 is_low_latency = true;
3529#if LOW_LATENCY_CAPTURE_USE_CASE
3530 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3531#endif
3532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003535 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003537 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303538 if (adev->mode != AUDIO_MODE_IN_CALL) {
3539 ret = -EINVAL;
3540 goto err_open;
3541 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003542 if (config->sample_rate == 0)
3543 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3544 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3545 config->sample_rate != 8000) {
3546 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3547 ret = -EINVAL;
3548 goto err_open;
3549 }
3550 if (config->format == AUDIO_FORMAT_DEFAULT)
3551 config->format = AUDIO_FORMAT_PCM_16_BIT;
3552 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3553 config->format = AUDIO_FORMAT_PCM_16_BIT;
3554 ret = -EINVAL;
3555 goto err_open;
3556 }
3557
3558 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3559 in->config = pcm_config_afe_proxy_record;
3560 in->config.channels = channel_count;
3561 in->config.rate = config->sample_rate;
3562 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003563 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003564 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003565 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3566 ret = -EINVAL;
3567 goto err_open;
3568 }
3569 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003570 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003571 }
Mingming Yine62d7842013-10-25 16:26:03 -07003572 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003573 audio_extn_compr_cap_format_supported(config->format) &&
3574 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003575 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003576 } else {
3577 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003578 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003579 buffer_size = get_input_buffer_size(config->sample_rate,
3580 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003581 channel_count,
3582 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003583 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003584 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3585 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3586 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3587 (in->config.rate == 8000 || in->config.rate == 16000) &&
3588 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3589 voice_extn_compress_voip_open_input_stream(in);
3590 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003593 /* This stream could be for sound trigger lab,
3594 get sound trigger pcm if present */
3595 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303596 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003599 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003600 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601
3602err_open:
3603 free(in);
3604 *stream_in = NULL;
3605 return ret;
3606}
3607
3608static void adev_close_input_stream(struct audio_hw_device *dev,
3609 struct audio_stream_in *stream)
3610{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003611 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003612 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003613 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303614
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303615 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003616
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303617 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003618 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303619
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003620 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303621 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003622 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303623 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003624 if (ret != 0)
3625 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3626 __func__, ret);
3627 } else
3628 in_standby(&stream->common);
3629
Mingming Yin7b762e72015-03-04 13:47:32 -08003630 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003631 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003632 audio_extn_ssr_deinit();
3633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
Mingming Yine62d7842013-10-25 16:26:03 -07003635 if(audio_extn_compr_cap_enabled() &&
3636 audio_extn_compr_cap_format_supported(in->config.format))
3637 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003638
3639 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 return;
3641}
3642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003643static int adev_dump(const audio_hw_device_t *device __unused,
3644 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645{
3646 return 0;
3647}
3648
3649static int adev_close(hw_device_t *device)
3650{
3651 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003652
3653 if (!adev)
3654 return 0;
3655
3656 pthread_mutex_lock(&adev_init_lock);
3657
3658 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003659 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003660 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003661 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003662 audio_route_free(adev->audio_route);
3663 free(adev->snd_dev_ref_cnt);
3664 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003665 if (adev->adm_deinit)
3666 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003667 free(device);
3668 adev = NULL;
3669 }
3670 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 return 0;
3673}
3674
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003675/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3676 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3677 * just that it _might_ work.
3678 */
3679static int period_size_is_plausible_for_low_latency(int period_size)
3680{
3681 switch (period_size) {
3682 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003683 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003684 case 240:
3685 case 320:
3686 case 480:
3687 return 1;
3688 default:
3689 return 0;
3690 }
3691}
3692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693static int adev_open(const hw_module_t *module, const char *name,
3694 hw_device_t **device)
3695{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003696 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003698 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3700
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003701 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003702 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003703 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003704 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003705 ALOGD("%s: returning existing instance of adev", __func__);
3706 ALOGD("%s: exit", __func__);
3707 pthread_mutex_unlock(&adev_init_lock);
3708 return 0;
3709 }
3710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 adev = calloc(1, sizeof(struct audio_device));
3712
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003713 if (!adev) {
3714 pthread_mutex_unlock(&adev_init_lock);
3715 return -ENOMEM;
3716 }
3717
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003718 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3721 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3722 adev->device.common.module = (struct hw_module_t *)module;
3723 adev->device.common.close = adev_close;
3724
3725 adev->device.init_check = adev_init_check;
3726 adev->device.set_voice_volume = adev_set_voice_volume;
3727 adev->device.set_master_volume = adev_set_master_volume;
3728 adev->device.get_master_volume = adev_get_master_volume;
3729 adev->device.set_master_mute = adev_set_master_mute;
3730 adev->device.get_master_mute = adev_get_master_mute;
3731 adev->device.set_mode = adev_set_mode;
3732 adev->device.set_mic_mute = adev_set_mic_mute;
3733 adev->device.get_mic_mute = adev_get_mic_mute;
3734 adev->device.set_parameters = adev_set_parameters;
3735 adev->device.get_parameters = adev_get_parameters;
3736 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3737 adev->device.open_output_stream = adev_open_output_stream;
3738 adev->device.close_output_stream = adev_close_output_stream;
3739 adev->device.open_input_stream = adev_open_input_stream;
3740 adev->device.close_input_stream = adev_close_input_stream;
3741 adev->device.dump = adev_dump;
3742
3743 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003745 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003746 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003749 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003750 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003751 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003752 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003753 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003754 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003755 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303756
3757 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3758 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003760 adev->platform = platform_init(adev);
3761 if (!adev->platform) {
3762 free(adev->snd_dev_ref_cnt);
3763 free(adev);
3764 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3765 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003766 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003767 return -EINVAL;
3768 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003769
Naresh Tanniru4c630392014-05-12 01:05:52 +05303770 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3771
Eric Laurentc4aef752013-09-12 17:45:53 -07003772 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3773 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3774 if (adev->visualizer_lib == NULL) {
3775 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3776 } else {
3777 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3778 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003779 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003780 "visualizer_hal_start_output");
3781 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003782 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003783 "visualizer_hal_stop_output");
3784 }
3785 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003786 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003787 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003788
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003789 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3790 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3791 if (adev->offload_effects_lib == NULL) {
3792 ALOGE("%s: DLOPEN failed for %s", __func__,
3793 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3794 } else {
3795 ALOGV("%s: DLOPEN successful for %s", __func__,
3796 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3797 adev->offload_effects_start_output =
3798 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3799 "offload_effects_bundle_hal_start_output");
3800 adev->offload_effects_stop_output =
3801 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3802 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003803 adev->offload_effects_set_hpx_state =
3804 (int (*)(bool))dlsym(adev->offload_effects_lib,
3805 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003806 }
3807 }
3808
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003809 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3810 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3811 if (adev->adm_lib == NULL) {
3812 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3813 } else {
3814 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3815 adev->adm_init = (adm_init_t)
3816 dlsym(adev->adm_lib, "adm_init");
3817 adev->adm_deinit = (adm_deinit_t)
3818 dlsym(adev->adm_lib, "adm_deinit");
3819 adev->adm_register_input_stream = (adm_register_input_stream_t)
3820 dlsym(adev->adm_lib, "adm_register_input_stream");
3821 adev->adm_register_output_stream = (adm_register_output_stream_t)
3822 dlsym(adev->adm_lib, "adm_register_output_stream");
3823 adev->adm_deregister_stream = (adm_deregister_stream_t)
3824 dlsym(adev->adm_lib, "adm_deregister_stream");
3825 adev->adm_request_focus = (adm_request_focus_t)
3826 dlsym(adev->adm_lib, "adm_request_focus");
3827 adev->adm_abandon_focus = (adm_abandon_focus_t)
3828 dlsym(adev->adm_lib, "adm_abandon_focus");
3829 }
3830 }
3831
Mingming Yin514a8bc2014-07-29 15:22:21 -07003832 adev->bt_wb_speech_enabled = false;
3833
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003834 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 *device = &adev->device.common;
3836
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003837 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3838 &adev->streams_output_cfg_list);
3839
Kiran Kandi910e1862013-10-29 13:29:42 -07003840 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003841
3842 char value[PROPERTY_VALUE_MAX];
3843 int trial;
3844 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3845 trial = atoi(value);
3846 if (period_size_is_plausible_for_low_latency(trial)) {
3847 pcm_config_low_latency.period_size = trial;
3848 pcm_config_low_latency.start_threshold = trial / 4;
3849 pcm_config_low_latency.avail_min = trial / 4;
3850 configured_low_latency_capture_period_size = trial;
3851 }
3852 }
3853 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3854 trial = atoi(value);
3855 if (period_size_is_plausible_for_low_latency(trial)) {
3856 configured_low_latency_capture_period_size = trial;
3857 }
3858 }
3859
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003860 pthread_mutex_unlock(&adev_init_lock);
3861
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003862 if (adev->adm_init)
3863 adev->adm_data = adev->adm_init();
3864
Eric Laurent994a6932013-07-17 11:51:42 -07003865 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 return 0;
3867}
3868
3869static struct hw_module_methods_t hal_module_methods = {
3870 .open = adev_open,
3871};
3872
3873struct audio_module HAL_MODULE_INFO_SYM = {
3874 .common = {
3875 .tag = HARDWARE_MODULE_TAG,
3876 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3877 .hal_api_version = HARDWARE_HAL_API_VERSION,
3878 .id = AUDIO_HARDWARE_MODULE_ID,
3879 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003880 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 .methods = &hal_module_methods,
3882 },
3883};