blob: df907bf74f61862708ccba9dd02c0192606d4a52 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700180 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700183 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700185 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700186 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800187 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800188 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700190
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700191 [USECASE_VOICE2_CALL] = "voice2-call",
192 [USECASE_VOLTE_CALL] = "volte-call",
193 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800194 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800195 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
196 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800197 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700198 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
199 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
200 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800201 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
202 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
203 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
204
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700205 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
206 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700207 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
208 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700209
210 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
211 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700212};
213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700214static const audio_usecase_t offload_usecases[] = {
215 USECASE_AUDIO_PLAYBACK_OFFLOAD,
216#ifdef MULTIPLE_OFFLOAD_ENABLED
217 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
225#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700226 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700227};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228
229#define STRING_TO_ENUM(string) { #string, string }
230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800231struct string_to_enum {
232 const char *name;
233 uint32_t value;
234};
235
236static const struct string_to_enum out_channels_name_to_enum_table[] = {
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
244};
245
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700246static const struct string_to_enum out_formats_name_to_enum_table[] = {
247 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
250};
251
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700252static struct audio_device *adev = NULL;
253static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700254static unsigned int audio_device_ref_count;
255
Haynes Mathew George5191a852013-09-11 14:19:36 -0700256static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800257
vivek mehtaa76401a2015-04-24 14:12:15 -0700258__attribute__ ((visibility ("default")))
259bool audio_hw_send_gain_dep_calibration(int level) {
260 bool ret_val = false;
261 ALOGV("%s: called ... ", __func__);
262
263 pthread_mutex_lock(&adev_init_lock);
264
265 if (adev != NULL && adev->platform != NULL) {
266 pthread_mutex_lock(&adev->lock);
267 ret_val = platform_send_gain_dep_cal(adev->platform, level);
268 pthread_mutex_unlock(&adev->lock);
269 } else {
270 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
271 }
272
273 pthread_mutex_unlock(&adev_init_lock);
274
275 return ret_val;
276}
277
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800278static int check_and_set_gapless_mode(struct audio_device *adev) {
279
280
281 char value[PROPERTY_VALUE_MAX] = {0};
282 bool gapless_enabled = false;
283 const char *mixer_ctl_name = "Compress Gapless Playback";
284 struct mixer_ctl *ctl;
285
286 ALOGV("%s:", __func__);
287 property_get("audio.offload.gapless.enabled", value, NULL);
288 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
289
290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
291 if (!ctl) {
292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
293 __func__, mixer_ctl_name);
294 return -EINVAL;
295 }
296
297 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
298 ALOGE("%s: Could not set gapless mode %d",
299 __func__, gapless_enabled);
300 return -EINVAL;
301 }
302 return 0;
303}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305static bool is_supported_format(audio_format_t format)
306{
Eric Laurent86e17132013-09-12 17:49:30 -0700307 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530308 format == AUDIO_FORMAT_AAC_LC ||
309 format == AUDIO_FORMAT_AAC_HE_V1 ||
310 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530311 format == AUDIO_FORMAT_AAC_ADTS_LC ||
312 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800314 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700316 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 format == AUDIO_FORMAT_ALAC ||
319 format == AUDIO_FORMAT_APE ||
320 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800321 format == AUDIO_FORMAT_WMA ||
322 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800323 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700324
325 return false;
326}
327
328static int get_snd_codec_id(audio_format_t format)
329{
330 int id = 0;
331
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 case AUDIO_FORMAT_MP3:
334 id = SND_AUDIOCODEC_MP3;
335 break;
336 case AUDIO_FORMAT_AAC:
337 id = SND_AUDIOCODEC_AAC;
338 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530339 case AUDIO_FORMAT_AAC_ADTS:
340 id = SND_AUDIOCODEC_AAC;
341 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530342 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700343 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800344 id = SND_AUDIOCODEC_PCM;
345 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700346 case AUDIO_FORMAT_FLAC:
347 id = SND_AUDIOCODEC_FLAC;
348 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530349 case AUDIO_FORMAT_ALAC:
350 id = SND_AUDIOCODEC_ALAC;
351 break;
352 case AUDIO_FORMAT_APE:
353 id = SND_AUDIOCODEC_APE;
354 break;
355 case AUDIO_FORMAT_VORBIS:
356 id = SND_AUDIOCODEC_VORBIS;
357 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800358 case AUDIO_FORMAT_WMA:
359 id = SND_AUDIOCODEC_WMA;
360 break;
361 case AUDIO_FORMAT_WMA_PRO:
362 id = SND_AUDIOCODEC_WMA_PRO;
363 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700364 default:
Mingming Yin90310102013-11-13 16:57:00 -0800365 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700366 }
367
368 return id;
369}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800370
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530371int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530372{
373 int snd_scard_state;
374
375 if (!adev)
376 return SND_CARD_STATE_OFFLINE;
377
378 pthread_mutex_lock(&adev->snd_card_status.lock);
379 snd_scard_state = adev->snd_card_status.state;
380 pthread_mutex_unlock(&adev->snd_card_status.lock);
381
382 return snd_scard_state;
383}
384
385static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
386{
387 if (!adev)
388 return -ENOSYS;
389
390 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700391 if (adev->snd_card_status.state != snd_scard_state) {
392 adev->snd_card_status.state = snd_scard_state;
393 platform_snd_card_update(adev->platform, snd_scard_state);
394 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530395 pthread_mutex_unlock(&adev->snd_card_status.lock);
396
397 return 0;
398}
399
Avinash Vaish71a8b972014-07-24 15:36:33 +0530400static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
401 struct audio_usecase *uc_info)
402{
403 struct listnode *node;
404 struct audio_usecase *usecase;
405
406 if (uc_info == NULL)
407 return -EINVAL;
408
409 /* Re-route all voice usecases on the shared backend other than the
410 specified usecase to new snd devices */
411 list_for_each(node, &adev->usecase_list) {
412 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800413 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530414 enable_audio_route(adev, usecase);
415 }
416 return 0;
417}
418
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700419int pcm_ioctl(struct pcm *pcm, int request, ...)
420{
421 va_list ap;
422 void * arg;
423 int pcm_fd = *(int*)pcm;
424
425 va_start(ap, request);
426 arg = va_arg(ap, void *);
427 va_end(ap);
428
429 return ioctl(pcm_fd, request, arg);
430}
431
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700432int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700433 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700436 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437
438 if (usecase == NULL)
439 return -EINVAL;
440
441 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
442
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700444 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700446 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800447
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800448#ifdef DS1_DOLBY_DAP_ENABLED
449 audio_extn_dolby_set_dmid(adev);
450 audio_extn_dolby_set_endpoint(adev);
451#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700452 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700453 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530454 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700455 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700456 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800457 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700458 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700459 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
460 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461 ALOGV("%s: exit", __func__);
462 return 0;
463}
464
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700466 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700468 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700469 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800470
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530471 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800472 return -EINVAL;
473
474 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 if (usecase->type == PCM_CAPTURE)
476 snd_device = usecase->in_snd_device;
477 else
478 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800479 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700480 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700481 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
482 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700483 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530484 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485 ALOGV("%s: exit", __func__);
486 return 0;
487}
488
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700489int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700490 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700492 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
493
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800494 if (snd_device < SND_DEVICE_MIN ||
495 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800496 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800497 return -EINVAL;
498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499
500 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700501
502 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
503 ALOGE("%s: Invalid sound device returned", __func__);
504 return -EINVAL;
505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700506 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700507 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700508 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700509 return 0;
510 }
511
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700512 if (audio_extn_spkr_prot_is_enabled())
513 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700514 /* start usb playback thread */
515 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
516 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
517 audio_extn_usb_start_playback(adev);
518
519 /* start usb capture thread */
520 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
521 audio_extn_usb_start_capture(adev);
522
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
524 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700525 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700526 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
527 adev->snd_dev_ref_cnt[snd_device]--;
528 return -EINVAL;
529 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200530 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800531 if (audio_extn_spkr_prot_start_processing(snd_device)) {
532 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200533 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800534 return -EINVAL;
535 }
536 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700537 ALOGV("%s: snd_device(%d: %s)", __func__,
538 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700539 /* due to the possibility of calibration overwrite between listen
540 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700541 audio_extn_sound_trigger_update_device_status(snd_device,
542 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530543 audio_extn_listen_update_device_status(snd_device,
544 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700545 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700547 audio_extn_sound_trigger_update_device_status(snd_device,
548 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530549 audio_extn_listen_update_device_status(snd_device,
550 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700551 return -EINVAL;
552 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300553 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700554 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 return 0;
557}
558
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700559int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700560 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
563
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800564 if (snd_device < SND_DEVICE_MIN ||
565 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800566 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 return -EINVAL;
568 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
570 ALOGE("%s: device ref cnt is already 0", __func__);
571 return -EINVAL;
572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700575
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700576 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
577 ALOGE("%s: Invalid sound device returned", __func__);
578 return -EINVAL;
579 }
580
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700582 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700583 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800584 /* exit usb play back thread */
585 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
586 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
587 audio_extn_usb_stop_playback();
588
589 /* exit usb capture thread */
590 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700591 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800592
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800593 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
594 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700595 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700596 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300597 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700598 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300599 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700600
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200601 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700602 audio_extn_sound_trigger_update_device_status(snd_device,
603 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530604 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800605 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800608 return 0;
609}
610
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611static void check_usecases_codec_backend(struct audio_device *adev,
612 struct audio_usecase *uc_info,
613 snd_device_t snd_device)
614{
615 struct listnode *node;
616 struct audio_usecase *usecase;
617 bool switch_device[AUDIO_USECASE_MAX];
618 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800619 int backend_idx = DEFAULT_CODEC_BACKEND;
620 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621
622 /*
623 * This function is to make sure that all the usecases that are active on
624 * the hardware codec backend are always routed to any one device that is
625 * handled by the hardware codec.
626 * For example, if low-latency and deep-buffer usecases are currently active
627 * on speaker and out_set_parameters(headset) is received on low-latency
628 * output, then we have to make sure deep-buffer is also switched to headset,
629 * because of the limitation that both the devices cannot be enabled
630 * at the same time as they share the same backend.
631 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700632 /*
633 * This call is to check if we need to force routing for a particular stream
634 * If there is a backend configuration change for the device when a
635 * new stream starts, then ADM needs to be closed and re-opened with the new
636 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800637 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700638 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
640 snd_device);
641 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800643 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800644 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 for (i = 0; i < AUDIO_USECASE_MAX; i++)
646 switch_device[i] = false;
647
648 list_for_each(node, &adev->usecase_list) {
649 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650
651 if (usecase == uc_info)
652 continue;
653 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
654 ALOGV("%s: backend_idx: %d,"
655 "usecase_backend_idx: %d, curr device: %s, usecase device:"
656 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530657 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800659 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700660 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800661 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
662 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530663 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800664 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700665 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700666 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 switch_device[usecase->id] = true;
668 num_uc_to_switch++;
669 }
670 }
671
672 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700673 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700674
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530675 /* Make sure the previous devices to be disabled first and then enable the
676 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 list_for_each(node, &adev->usecase_list) {
678 usecase = node_to_item(node, struct audio_usecase, list);
679 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700680 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 }
682 }
683
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700684 list_for_each(node, &adev->usecase_list) {
685 usecase = node_to_item(node, struct audio_usecase, list);
686 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700687 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700688 }
689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 /* Re-route all the usecases on the shared backend other than the
692 specified usecase to new snd devices */
693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530695 /* Update the out_snd_device only for the usecases that are enabled here */
696 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
697 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530698 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 }
700 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700701 }
702}
703
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704static void check_and_route_capture_usecases(struct audio_device *adev,
705 struct audio_usecase *uc_info,
706 snd_device_t snd_device)
707{
708 struct listnode *node;
709 struct audio_usecase *usecase;
710 bool switch_device[AUDIO_USECASE_MAX];
711 int i, num_uc_to_switch = 0;
712
713 /*
714 * This function is to make sure that all the active capture usecases
715 * are always routed to the same input sound device.
716 * For example, if audio-record and voice-call usecases are currently
717 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
718 * is received for voice call then we have to make sure that audio-record
719 * usecase is also switched to earpiece i.e. voice-dmic-ef,
720 * because of the limitation that two devices cannot be enabled
721 * at the same time if they share the same backend.
722 */
723 for (i = 0; i < AUDIO_USECASE_MAX; i++)
724 switch_device[i] = false;
725
726 list_for_each(node, &adev->usecase_list) {
727 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800728 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700730 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700731 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
732 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700733 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
735 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700736 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700737 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 switch_device[usecase->id] = true;
739 num_uc_to_switch++;
740 }
741 }
742
743 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700744 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530746 /* Make sure the previous devices to be disabled first and then enable the
747 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 list_for_each(node, &adev->usecase_list) {
749 usecase = node_to_item(node, struct audio_usecase, list);
750 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700751 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800752 }
753 }
754
755 list_for_each(node, &adev->usecase_list) {
756 usecase = node_to_item(node, struct audio_usecase, list);
757 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700758 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700759 }
760 }
761
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 /* Re-route all the usecases on the shared backend other than the
763 specified usecase to new snd devices */
764 list_for_each(node, &adev->usecase_list) {
765 usecase = node_to_item(node, struct audio_usecase, list);
766 /* Update the in_snd_device only before enabling the audio route */
767 if (switch_device[usecase->id] ) {
768 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800769 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530770 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771 }
772 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700773 }
774}
775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700777static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700779 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700780 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781
782 switch (channels) {
783 /*
784 * Do not handle stereo output in Multi-channel cases
785 * Stereo case is handled in normal playback path
786 */
787 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700788 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800794 break;
795 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700796 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
799 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803 break;
804 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700805 ALOGE("HDMI does not support multi channel playback");
806 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 break;
808 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700809 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810}
811
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800812audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
813 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700814{
815 struct audio_usecase *usecase;
816 struct listnode *node;
817
818 list_for_each(node, &adev->usecase_list) {
819 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800820 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700821 ALOGV("%s: usecase id %d", __func__, usecase->id);
822 return usecase->id;
823 }
824 }
825 return USECASE_INVALID;
826}
827
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700828struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700829 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830{
831 struct audio_usecase *usecase;
832 struct listnode *node;
833
834 list_for_each(node, &adev->usecase_list) {
835 usecase = node_to_item(node, struct audio_usecase, list);
836 if (usecase->id == uc_id)
837 return usecase;
838 }
839 return NULL;
840}
841
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800844 snd_device_t out_snd_device = SND_DEVICE_NONE;
845 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 struct audio_usecase *usecase = NULL;
847 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800848 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800849 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800850 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800851 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700854 usecase = get_usecase_from_list(adev, uc_id);
855 if (usecase == NULL) {
856 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
857 return -EINVAL;
858 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800859
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800860 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800861 (usecase->type == VOIP_CALL) ||
862 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700863 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800864 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700865 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700866 usecase->devices = usecase->stream.out->devices;
867 } else {
868 /*
869 * If the voice call is active, use the sound devices of voice call usecase
870 * so that it would not result any device switch. All the usecases will
871 * be switched to new device when select_devices() is called for voice call
872 * usecase. This is to avoid switching devices for voice call when
873 * check_usecases_codec_backend() is called below.
874 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700875 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700876 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800877 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700878 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
879 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 in_snd_device = vc_usecase->in_snd_device;
881 out_snd_device = vc_usecase->out_snd_device;
882 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800883 } else if (voice_extn_compress_voip_is_active(adev)) {
884 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700885 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530886 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700887 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800888 in_snd_device = voip_usecase->in_snd_device;
889 out_snd_device = voip_usecase->out_snd_device;
890 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800891 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800892 hfp_ucid = audio_extn_hfp_get_usecase();
893 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700894 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800895 in_snd_device = hfp_usecase->in_snd_device;
896 out_snd_device = hfp_usecase->out_snd_device;
897 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 if (usecase->type == PCM_PLAYBACK) {
900 usecase->devices = usecase->stream.out->devices;
901 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700902 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700903 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800904 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700905 if (usecase->stream.out == adev->primary_output &&
906 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800907 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700908 select_devices(adev, adev->active_input->usecase);
909 }
910 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 } else if (usecase->type == PCM_CAPTURE) {
912 usecase->devices = usecase->stream.in->device;
913 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700914 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700915 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530916 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
917 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
918 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
919 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700921 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700922 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
923 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700924 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700925 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700926 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 }
928 }
929
930 if (out_snd_device == usecase->out_snd_device &&
931 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 return 0;
933 }
934
sangwoobc677242013-08-08 16:53:43 +0900935 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 out_snd_device, platform_get_snd_device_name(out_snd_device),
937 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939 /*
940 * Limitation: While in call, to do a device switch we need to disable
941 * and enable both RX and TX devices though one of them is same as current
942 * device.
943 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700944 if ((usecase->type == VOICE_CALL) &&
945 (usecase->in_snd_device != SND_DEVICE_NONE) &&
946 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700947 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700948 }
949
950 if (((usecase->type == VOICE_CALL) ||
951 (usecase->type == VOIP_CALL)) &&
952 (usecase->out_snd_device != SND_DEVICE_NONE)) {
953 /* Disable sidetone only if voice/voip call already exists */
954 if (voice_is_call_state_active(adev) ||
955 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700956 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800957 }
958
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 /* Disable current sound devices */
960 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 }
964
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700965 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700966 disable_audio_route(adev, usecase);
967 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 }
969
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800970 /* Applicable only on the targets that has external modem.
971 * New device information should be sent to modem before enabling
972 * the devices to reduce in-call device switch time.
973 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700974 if ((usecase->type == VOICE_CALL) &&
975 (usecase->in_snd_device != SND_DEVICE_NONE) &&
976 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800977 status = platform_switch_voice_call_enable_device_config(adev->platform,
978 out_snd_device,
979 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700980 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800981
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982 /* Enable new sound devices */
983 if (out_snd_device != SND_DEVICE_NONE) {
984 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
985 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700986 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987 }
988
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 if (in_snd_device != SND_DEVICE_NONE) {
990 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700991 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993
Avinash Vaish71a8b972014-07-24 15:36:33 +0530994 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700995 status = platform_switch_voice_call_device_post(adev->platform,
996 out_snd_device,
997 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530998 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700999 /* Enable sidetone only if voice/voip call already exists */
1000 if (voice_is_call_state_active(adev) ||
1001 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001002 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301003 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001004
sangwoo170731f2013-06-08 15:36:36 +09001005 usecase->in_snd_device = in_snd_device;
1006 usecase->out_snd_device = out_snd_device;
1007
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301008 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001009 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301010 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001011 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301012 usecase->stream.out->flags,
1013 usecase->stream.out->format,
1014 usecase->stream.out->sample_rate,
1015 usecase->stream.out->bit_width,
1016 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001017 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301018 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001019
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001020 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001021
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001022 /* Applicable only on the targets that has external modem.
1023 * Enable device command should be sent to modem only after
1024 * enabling voice call mixer controls
1025 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001026 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001027 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1028 out_snd_device,
1029 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301030 ALOGD("%s: done",__func__);
1031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 return status;
1033}
1034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035static int stop_input_stream(struct stream_in *in)
1036{
1037 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 struct audio_usecase *uc_info;
1039 struct audio_device *adev = in->dev;
1040
Eric Laurentc8400632013-02-14 19:04:54 -08001041 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042
Eric Laurent994a6932013-07-17 11:51:42 -07001043 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 uc_info = get_usecase_from_list(adev, in->usecase);
1046 if (uc_info == NULL) {
1047 ALOGE("%s: Could not find the usecase (%d) in the list",
1048 __func__, in->usecase);
1049 return -EINVAL;
1050 }
1051
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001052 /* Close in-call recording streams */
1053 voice_check_and_stop_incall_rec_usecase(adev, in);
1054
Eric Laurent150dbfe2013-02-27 14:31:02 -08001055 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001056 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057
1058 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001061 list_remove(&uc_info->list);
1062 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Eric Laurent994a6932013-07-17 11:51:42 -07001064 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065 return ret;
1066}
1067
1068int start_input_stream(struct stream_in *in)
1069{
1070 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001071 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 struct audio_usecase *uc_info;
1073 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301074 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075
Mingming Yin2664a5b2015-09-03 10:53:11 -07001076 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1077 if (get_usecase_from_list(adev, usecase) == NULL)
1078 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301079 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1080 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001081
Naresh Tanniru80659832014-06-04 18:17:56 +05301082
1083 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301084 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301085 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301086 goto error_config;
1087 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301088
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001089 /* Check if source matches incall recording usecase criteria */
1090 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1091 if (ret)
1092 goto error_config;
1093 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001094 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1095
1096 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1097 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1098 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1099 goto error_config;
1100 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001101
Eric Laurentb23d5282013-05-14 15:27:20 -07001102 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 if (in->pcm_device_id < 0) {
1104 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1105 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001106 ret = -EINVAL;
1107 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109
1110 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001112
1113 if (!uc_info) {
1114 ret = -ENOMEM;
1115 goto error_config;
1116 }
1117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118 uc_info->id = in->usecase;
1119 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001120 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 uc_info->devices = in->device;
1122 uc_info->in_snd_device = SND_DEVICE_NONE;
1123 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001125 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301126 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128
Eric Laurentc8400632013-02-14 19:04:54 -08001129 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001130 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1131
1132 unsigned int flags = PCM_IN;
1133 unsigned int pcm_open_retry_count = 0;
1134
1135 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1136 flags |= PCM_MMAP | PCM_NOIRQ;
1137 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1138 }
1139
1140 while (1) {
1141 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1142 flags, &in->config);
1143 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1144 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1145 if (in->pcm != NULL) {
1146 pcm_close(in->pcm);
1147 in->pcm = NULL;
1148 }
1149 if (pcm_open_retry_count-- == 0) {
1150 ret = -EIO;
1151 goto error_open;
1152 }
1153 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1154 continue;
1155 }
1156 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301158 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301159
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001160 ALOGV("%s: pcm_prepare start", __func__);
1161 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001162 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001163
Eric Laurentc8400632013-02-14 19:04:54 -08001164 return ret;
1165
1166error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301168 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001169
1170error_config:
1171 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001172 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001173
1174 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175}
1176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001177/* must be called with out->lock locked */
1178static int send_offload_cmd_l(struct stream_out* out, int command)
1179{
1180 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1181
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001182 if (!cmd) {
1183 ALOGE("failed to allocate mem for command 0x%x", command);
1184 return -ENOMEM;
1185 }
1186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187 ALOGVV("%s %d", __func__, command);
1188
1189 cmd->cmd = command;
1190 list_add_tail(&out->offload_cmd_list, &cmd->node);
1191 pthread_cond_signal(&out->offload_cond);
1192 return 0;
1193}
1194
1195/* must be called iwth out->lock locked */
1196static void stop_compressed_output_l(struct stream_out *out)
1197{
1198 out->offload_state = OFFLOAD_STATE_IDLE;
1199 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001200 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001201 if (out->compr != NULL) {
1202 compress_stop(out->compr);
1203 while (out->offload_thread_blocked) {
1204 pthread_cond_wait(&out->cond, &out->lock);
1205 }
1206 }
1207}
1208
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001209bool is_offload_usecase(audio_usecase_t uc_id)
1210{
1211 unsigned int i;
1212 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1213 if (uc_id == offload_usecases[i])
1214 return true;
1215 }
1216 return false;
1217}
1218
1219static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1220{
1221 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1222 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1223 char value[PROPERTY_VALUE_MAX] = {0};
1224
1225 property_get("audio.offload.multiple.enabled", value, NULL);
1226 if (!(atoi(value) || !strncmp("true", value, 4)))
1227 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1228
1229 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1230 for (i = 0; i < num_usecase; i++) {
1231 if (!(adev->offload_usecases_state & (0x1<<i))) {
1232 adev->offload_usecases_state |= 0x1 << i;
1233 ret = offload_usecases[i];
1234 break;
1235 }
1236 }
1237 ALOGV("%s: offload usecase is %d", __func__, ret);
1238 return ret;
1239}
1240
1241static void free_offload_usecase(struct audio_device *adev,
1242 audio_usecase_t uc_id)
1243{
1244 unsigned int i;
1245 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1246 if (offload_usecases[i] == uc_id) {
1247 adev->offload_usecases_state &= ~(0x1<<i);
1248 break;
1249 }
1250 }
1251 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1252}
1253
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001254static void *offload_thread_loop(void *context)
1255{
1256 struct stream_out *out = (struct stream_out *) context;
1257 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001258 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001259
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1261 set_sched_policy(0, SP_FOREGROUND);
1262 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1263
1264 ALOGV("%s", __func__);
1265 pthread_mutex_lock(&out->lock);
1266 for (;;) {
1267 struct offload_cmd *cmd = NULL;
1268 stream_callback_event_t event;
1269 bool send_callback = false;
1270
1271 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1272 __func__, list_empty(&out->offload_cmd_list),
1273 out->offload_state);
1274 if (list_empty(&out->offload_cmd_list)) {
1275 ALOGV("%s SLEEPING", __func__);
1276 pthread_cond_wait(&out->offload_cond, &out->lock);
1277 ALOGV("%s RUNNING", __func__);
1278 continue;
1279 }
1280
1281 item = list_head(&out->offload_cmd_list);
1282 cmd = node_to_item(item, struct offload_cmd, node);
1283 list_remove(item);
1284
1285 ALOGVV("%s STATE %d CMD %d out->compr %p",
1286 __func__, out->offload_state, cmd->cmd, out->compr);
1287
1288 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1289 free(cmd);
1290 break;
1291 }
1292
1293 if (out->compr == NULL) {
1294 ALOGE("%s: Compress handle is NULL", __func__);
1295 pthread_cond_signal(&out->cond);
1296 continue;
1297 }
1298 out->offload_thread_blocked = true;
1299 pthread_mutex_unlock(&out->lock);
1300 send_callback = false;
1301 switch(cmd->cmd) {
1302 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001303 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001305 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 send_callback = true;
1307 event = STREAM_CBK_EVENT_WRITE_READY;
1308 break;
1309 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001310 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301311 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001312 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301313 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001314 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301315 if (ret < 0)
1316 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301317 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301318 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001319 compress_drain(out->compr);
1320 else
1321 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301322 if (ret != -ENETRESET) {
1323 send_callback = true;
1324 event = STREAM_CBK_EVENT_DRAIN_READY;
1325 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1326 } else
1327 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001328 break;
1329 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001330 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001331 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001332 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001333 send_callback = true;
1334 event = STREAM_CBK_EVENT_DRAIN_READY;
1335 break;
1336 default:
1337 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1338 break;
1339 }
1340 pthread_mutex_lock(&out->lock);
1341 out->offload_thread_blocked = false;
1342 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001343 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001344 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001346 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 free(cmd);
1348 }
1349
1350 pthread_cond_signal(&out->cond);
1351 while (!list_empty(&out->offload_cmd_list)) {
1352 item = list_head(&out->offload_cmd_list);
1353 list_remove(item);
1354 free(node_to_item(item, struct offload_cmd, node));
1355 }
1356 pthread_mutex_unlock(&out->lock);
1357
1358 return NULL;
1359}
1360
1361static int create_offload_callback_thread(struct stream_out *out)
1362{
1363 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1364 list_init(&out->offload_cmd_list);
1365 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1366 offload_thread_loop, out);
1367 return 0;
1368}
1369
1370static int destroy_offload_callback_thread(struct stream_out *out)
1371{
1372 pthread_mutex_lock(&out->lock);
1373 stop_compressed_output_l(out);
1374 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1375
1376 pthread_mutex_unlock(&out->lock);
1377 pthread_join(out->offload_thread, (void **) NULL);
1378 pthread_cond_destroy(&out->offload_cond);
1379
1380 return 0;
1381}
1382
Eric Laurent07eeafd2013-10-06 12:52:49 -07001383static bool allow_hdmi_channel_config(struct audio_device *adev)
1384{
1385 struct listnode *node;
1386 struct audio_usecase *usecase;
1387 bool ret = true;
1388
1389 list_for_each(node, &adev->usecase_list) {
1390 usecase = node_to_item(node, struct audio_usecase, list);
1391 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1392 /*
1393 * If voice call is already existing, do not proceed further to avoid
1394 * disabling/enabling both RX and TX devices, CSD calls, etc.
1395 * Once the voice call done, the HDMI channels can be configured to
1396 * max channels of remaining use cases.
1397 */
1398 if (usecase->id == USECASE_VOICE_CALL) {
1399 ALOGD("%s: voice call is active, no change in HDMI channels",
1400 __func__);
1401 ret = false;
1402 break;
1403 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1404 ALOGD("%s: multi channel playback is active, "
1405 "no change in HDMI channels", __func__);
1406 ret = false;
1407 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001408 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001409 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001410 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1411 ", no change in HDMI channels", __func__,
1412 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001413 ret = false;
1414 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001415 }
1416 }
1417 }
1418 return ret;
1419}
1420
1421static int check_and_set_hdmi_channels(struct audio_device *adev,
1422 unsigned int channels)
1423{
1424 struct listnode *node;
1425 struct audio_usecase *usecase;
1426
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001427 unsigned int supported_channels = platform_edid_get_max_channels(
1428 adev->platform);
1429 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 /* Check if change in HDMI channel config is allowed */
1431 if (!allow_hdmi_channel_config(adev))
1432 return 0;
1433
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001434 if (channels > supported_channels)
1435 channels = supported_channels;
1436
Eric Laurent07eeafd2013-10-06 12:52:49 -07001437 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001438 ALOGD("%s: Requested channels are same as current channels(%d)",
1439 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001440 return 0;
1441 }
1442
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001443 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001444 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001445 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001446 adev->cur_hdmi_channels = channels;
1447
1448 /*
1449 * Deroute all the playback streams routed to HDMI so that
1450 * the back end is deactivated. Note that backend will not
1451 * be deactivated if any one stream is connected to it.
1452 */
1453 list_for_each(node, &adev->usecase_list) {
1454 usecase = node_to_item(node, struct audio_usecase, list);
1455 if (usecase->type == PCM_PLAYBACK &&
1456 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001457 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001458 }
1459 }
1460
1461 /*
1462 * Enable all the streams disabled above. Now the HDMI backend
1463 * will be activated with new channel configuration
1464 */
1465 list_for_each(node, &adev->usecase_list) {
1466 usecase = node_to_item(node, struct audio_usecase, list);
1467 if (usecase->type == PCM_PLAYBACK &&
1468 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001469 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001470 }
1471 }
1472
1473 return 0;
1474}
1475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476static int stop_output_stream(struct stream_out *out)
1477{
1478 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479 struct audio_usecase *uc_info;
1480 struct audio_device *adev = out->dev;
1481
Eric Laurent994a6932013-07-17 11:51:42 -07001482 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 uc_info = get_usecase_from_list(adev, out->usecase);
1485 if (uc_info == NULL) {
1486 ALOGE("%s: Could not find the usecase (%d) in the list",
1487 __func__, out->usecase);
1488 return -EINVAL;
1489 }
1490
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001491 if (is_offload_usecase(out->usecase) &&
1492 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001493 if (adev->visualizer_stop_output != NULL)
1494 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001495
1496 audio_extn_dts_remove_state_notifier_node(out->usecase);
1497
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001498 if (adev->offload_effects_stop_output != NULL)
1499 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1500 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001501
Eric Laurent150dbfe2013-02-27 14:31:02 -08001502 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001503 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001504
1505 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001506 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001508 list_remove(&uc_info->list);
1509 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001511 if (is_offload_usecase(out->usecase) &&
1512 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1513 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1514 ALOGV("Disable passthrough , reset mixer to pcm");
1515 /* NO_PASSTHROUGH */
1516 out->compr_config.codec->compr_passthr = 0;
1517 audio_extn_dolby_set_hdmi_config(adev, out);
1518 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1519 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001520 /* Must be called after removing the usecase from list */
1521 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1522 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1523
Eric Laurent994a6932013-07-17 11:51:42 -07001524 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 return ret;
1526}
1527
1528int start_output_stream(struct stream_out *out)
1529{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001531 int sink_channels = 0;
1532 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 struct audio_usecase *uc_info;
1534 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301535 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001537 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1538 ret = -EINVAL;
1539 goto error_config;
1540 }
1541
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301542 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1543 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1544 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301545
Naresh Tanniru80659832014-06-04 18:17:56 +05301546 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301547 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301548 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301549 goto error_config;
1550 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301551
Eric Laurentb23d5282013-05-14 15:27:20 -07001552 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 if (out->pcm_device_id < 0) {
1554 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1555 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001556 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001557 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558 }
1559
1560 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001561
1562 if (!uc_info) {
1563 ret = -ENOMEM;
1564 goto error_config;
1565 }
1566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 uc_info->id = out->usecase;
1568 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001569 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 uc_info->devices = out->devices;
1571 uc_info->in_snd_device = SND_DEVICE_NONE;
1572 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001573 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001574 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001575 if (is_offload_usecase(out->usecase)) {
1576 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001577 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1578 }
1579 }
Mingming Yin9c041392014-05-01 15:37:31 -07001580 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1581 if (!strncmp("true", prop_value, 4)) {
1582 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001583 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1584 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001585 check_and_set_hdmi_channels(adev, sink_channels);
1586 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001587 if (is_offload_usecase(out->usecase)) {
1588 unsigned int ch_count = out->compr_config.codec->ch_in;
1589 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1590 /* backend channel config for passthrough stream is stereo */
1591 ch_count = 2;
1592 check_and_set_hdmi_channels(adev, ch_count);
1593 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001594 check_and_set_hdmi_channels(adev, out->config.channels);
1595 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001596 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001597 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001598 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600 select_devices(adev, out->usecase);
1601
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001602 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1603 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001604 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001605 unsigned int flags = PCM_OUT;
1606 unsigned int pcm_open_retry_count = 0;
1607 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1608 flags |= PCM_MMAP | PCM_NOIRQ;
1609 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1610 } else
1611 flags |= PCM_MONOTONIC;
1612
1613 while (1) {
1614 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1615 flags, &out->config);
1616 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1617 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1618 if (out->pcm != NULL) {
1619 pcm_close(out->pcm);
1620 out->pcm = NULL;
1621 }
1622 if (pcm_open_retry_count-- == 0) {
1623 ret = -EIO;
1624 goto error_open;
1625 }
1626 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1627 continue;
1628 }
1629 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001630 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001631
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001632 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1633 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001634
1635 ALOGV("%s: pcm_prepare start", __func__);
1636 if (pcm_is_ready(out->pcm))
1637 pcm_prepare(out->pcm);
1638
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001640 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1641 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001643 out->compr = compress_open(adev->snd_card,
1644 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645 COMPRESS_IN, &out->compr_config);
1646 if (out->compr && !is_compress_ready(out->compr)) {
1647 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1648 compress_close(out->compr);
1649 out->compr = NULL;
1650 ret = -EIO;
1651 goto error_open;
1652 }
1653 if (out->offload_callback)
1654 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001655
Fred Oh3f43e742015-03-04 18:42:34 -08001656 /* Since small bufs uses blocking writes, a write will be blocked
1657 for the default max poll time (20s) in the event of an SSR.
1658 Reduce the poll time to observe and deal with SSR faster.
1659 */
1660 if (out->use_small_bufs) {
1661 compress_set_max_poll_wait(out->compr, 1000);
1662 }
1663
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001664 audio_extn_dts_create_state_notifier_node(out->usecase);
1665 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1666 popcount(out->channel_mask),
1667 out->playback_started);
1668
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001669#ifdef DS1_DOLBY_DDP_ENABLED
1670 if (audio_extn_is_dolby_format(out->format))
1671 audio_extn_dolby_send_ddp_endp_params(adev);
1672#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001673 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1674 if (adev->visualizer_start_output != NULL)
1675 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1676 if (adev->offload_effects_start_output != NULL)
1677 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001678 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001681
Eric Laurent994a6932013-07-17 11:51:42 -07001682 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001685error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001687error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001688 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689}
1690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691static int check_input_parameters(uint32_t sample_rate,
1692 audio_format_t format,
1693 int channel_count)
1694{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001695 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001697 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001698 !voice_extn_compress_voip_is_format_supported(format) &&
1699 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001700
1701 switch (channel_count) {
1702 case 1:
1703 case 2:
1704 case 6:
1705 break;
1706 default:
1707 ret = -EINVAL;
1708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
1710 switch (sample_rate) {
1711 case 8000:
1712 case 11025:
1713 case 12000:
1714 case 16000:
1715 case 22050:
1716 case 24000:
1717 case 32000:
1718 case 44100:
1719 case 48000:
1720 break;
1721 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001722 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 }
1724
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001725 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
1728static size_t get_input_buffer_size(uint32_t sample_rate,
1729 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001730 int channel_count,
1731 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732{
1733 size_t size = 0;
1734
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001735 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1736 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001738 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001739 if (is_low_latency)
1740 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001741 /* ToDo: should use frame_size computed based on the format and
1742 channel_count here. */
1743 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001745 /* make sure the size is multiple of 32 bytes
1746 * At 48 kHz mono 16-bit PCM:
1747 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1748 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1749 */
1750 size += 0x1f;
1751 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001752
1753 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
1756static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1757{
1758 struct stream_out *out = (struct stream_out *)stream;
1759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761}
1762
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001763static int out_set_sample_rate(struct audio_stream *stream __unused,
1764 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765{
1766 return -ENOSYS;
1767}
1768
1769static size_t out_get_buffer_size(const struct audio_stream *stream)
1770{
1771 struct stream_out *out = (struct stream_out *)stream;
1772
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001773 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001775 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1776 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001778 return out->config.period_size *
1779 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780}
1781
1782static uint32_t out_get_channels(const struct audio_stream *stream)
1783{
1784 struct stream_out *out = (struct stream_out *)stream;
1785
1786 return out->channel_mask;
1787}
1788
1789static audio_format_t out_get_format(const struct audio_stream *stream)
1790{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 struct stream_out *out = (struct stream_out *)stream;
1792
1793 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794}
1795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001796static int out_set_format(struct audio_stream *stream __unused,
1797 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798{
1799 return -ENOSYS;
1800}
1801
1802static int out_standby(struct audio_stream *stream)
1803{
1804 struct stream_out *out = (struct stream_out *)stream;
1805 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301807 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1808 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001809 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1810 /* Ignore standby in case of voip call because the voip output
1811 * stream is closed in adev_close_output_stream()
1812 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301813 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001814 return 0;
1815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001819 if (adev->adm_deregister_stream)
1820 adev->adm_deregister_stream(adev->adm_data, out->handle);
1821
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001822 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001824 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 if (out->pcm) {
1826 pcm_close(out->pcm);
1827 out->pcm = NULL;
1828 }
1829 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001830 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 out->gapless_mdata.encoder_delay = 0;
1833 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 if (out->compr != NULL) {
1835 compress_close(out->compr);
1836 out->compr = NULL;
1837 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001840 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 }
1842 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001843 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 return 0;
1845}
1846
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001847static int out_dump(const struct audio_stream *stream __unused,
1848 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849{
1850 return 0;
1851}
1852
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1854{
1855 int ret = 0;
1856 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001857 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001858
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001860 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 return -EINVAL;
1862 }
1863
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301864 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001865
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001866 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1867 if(ret >= 0)
1868 is_meta_data_params = true;
1869 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301870 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001871 is_meta_data_params = true;
1872 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301873 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001874 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001875 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1876 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001877 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301878 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001879 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001880 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1881 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001882 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301883 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001884 }
1885
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001886 if(!is_meta_data_params) {
1887 ALOGV("%s: Not gapless meta data params", __func__);
1888 return 0;
1889 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001890 out->send_new_metadata = 1;
1891 ALOGV("%s new encoder delay %u and padding %u", __func__,
1892 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1893
1894 return 0;
1895}
1896
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001897static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1898{
1899 return out == adev->primary_output || out == adev->voice_tx_output;
1900}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1903{
1904 struct stream_out *out = (struct stream_out *)stream;
1905 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001906 struct audio_usecase *usecase;
1907 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 struct str_parms *parms;
1909 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001910 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001911 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912
sangwoobc677242013-08-08 16:53:43 +09001913 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001914 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301916 if (!parms)
1917 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001918 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1919 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001922 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301925 * When HDMI cable is unplugged/usb hs is disconnected the
1926 * music playback is paused and the policy manager sends routing=0
1927 * But the audioflingercontinues to write data until standby time
1928 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001929 * Avoid this by routing audio to speaker until standby.
1930 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301931 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1932 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001933 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001934 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1935 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001936 }
1937
1938 /*
1939 * select_devices() call below switches all the usecases on the same
1940 * backend to the new device. Refer to check_usecases_codec_backend() in
1941 * the select_devices(). But how do we undo this?
1942 *
1943 * For example, music playback is active on headset (deep-buffer usecase)
1944 * and if we go to ringtones and select a ringtone, low-latency usecase
1945 * will be started on headset+speaker. As we can't enable headset+speaker
1946 * and headset devices at the same time, select_devices() switches the music
1947 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1948 * So when the ringtone playback is completed, how do we undo the same?
1949 *
1950 * We are relying on the out_set_parameters() call on deep-buffer output,
1951 * once the ringtone playback is ended.
1952 * NOTE: We should not check if the current devices are same as new devices.
1953 * Because select_devices() must be called to switch back the music
1954 * playback to headset.
1955 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001956 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001957 out->devices = val;
1958
1959 if (!out->standby)
1960 select_devices(adev, out->usecase);
1961
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001962 if (output_drives_call(adev, out)) {
1963 if(!voice_is_in_call(adev)) {
1964 if (adev->mode == AUDIO_MODE_IN_CALL) {
1965 adev->current_call_output = out;
1966 ret = voice_start_call(adev);
1967 }
1968 } else {
1969 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001970 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001971 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001972 }
1973 }
1974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001976 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001978
1979 if (out == adev->primary_output) {
1980 pthread_mutex_lock(&adev->lock);
1981 audio_extn_set_parameters(adev, parms);
1982 pthread_mutex_unlock(&adev->lock);
1983 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001984 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001985 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001986 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001987
1988 audio_extn_dts_create_state_notifier_node(out->usecase);
1989 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1990 popcount(out->channel_mask),
1991 out->playback_started);
1992
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001993 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001994 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301997error:
Eric Laurent994a6932013-07-17 11:51:42 -07001998 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 return ret;
2000}
2001
2002static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2003{
2004 struct stream_out *out = (struct stream_out *)stream;
2005 struct str_parms *query = str_parms_create_str(keys);
2006 char *str;
2007 char value[256];
2008 struct str_parms *reply = str_parms_create();
2009 size_t i, j;
2010 int ret;
2011 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002012
2013 if (!query || !reply) {
2014 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2015 return NULL;
2016 }
2017
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2020 if (ret >= 0) {
2021 value[0] = '\0';
2022 i = 0;
2023 while (out->supported_channel_masks[i] != 0) {
2024 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2025 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2026 if (!first) {
2027 strcat(value, "|");
2028 }
2029 strcat(value, out_channels_name_to_enum_table[j].name);
2030 first = false;
2031 break;
2032 }
2033 }
2034 i++;
2035 }
2036 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2037 str = str_parms_to_str(reply);
2038 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002039 voice_extn_out_get_parameters(out, query, reply);
2040 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002041 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002042 free(str);
2043 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002044 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002046
2047 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2048 if (ret >= 0) {
2049 value[0] = '\0';
2050 i = 0;
2051 first = true;
2052 while (out->supported_formats[i] != 0) {
2053 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2054 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2055 if (!first) {
2056 strcat(value, "|");
2057 }
2058 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2059 first = false;
2060 break;
2061 }
2062 }
2063 i++;
2064 }
2065 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2066 str = str_parms_to_str(reply);
2067 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 str_parms_destroy(query);
2069 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002070 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 return str;
2072}
2073
2074static uint32_t out_get_latency(const struct audio_stream_out *stream)
2075{
2076 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002077 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078
Alexy Josephaa54c872014-12-03 02:46:47 -08002079 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002080 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002081 } else {
2082 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002084 }
2085
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302086 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002087 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088}
2089
2090static int out_set_volume(struct audio_stream_out *stream, float left,
2091 float right)
2092{
Eric Laurenta9024de2013-04-04 09:19:12 -07002093 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 int volume[2];
2095
Eric Laurenta9024de2013-04-04 09:19:12 -07002096 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2097 /* only take left channel into account: the API is for stereo anyway */
2098 out->muted = (left == 0.0f);
2099 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002100 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002101 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2102 /*
2103 * Set mute or umute on HDMI passthrough stream.
2104 * Only take left channel into account.
2105 * Mute is 0 and unmute 1
2106 */
2107 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2108 } else {
2109 char mixer_ctl_name[128];
2110 struct audio_device *adev = out->dev;
2111 struct mixer_ctl *ctl;
2112 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002113 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002115 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2116 "Compress Playback %d Volume", pcm_device_id);
2117 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2118 if (!ctl) {
2119 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2120 __func__, mixer_ctl_name);
2121 return -EINVAL;
2122 }
2123 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2124 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2125 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2126 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002128 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 return -ENOSYS;
2131}
2132
2133static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2134 size_t bytes)
2135{
2136 struct stream_out *out = (struct stream_out *)stream;
2137 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302138 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002139 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142
Naresh Tanniru80659832014-06-04 18:17:56 +05302143 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002144 // increase written size during SSR to avoid mismatch
2145 // with the written frames count in AF
2146 if (!is_offload_usecase(out->usecase))
2147 out->written += bytes / (out->config.channels * sizeof(short));
2148
Naresh Tanniru80659832014-06-04 18:17:56 +05302149 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302150 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302151 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302152 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002153 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 //during SSR for compress usecase we should return error to flinger
2155 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2156 pthread_mutex_unlock(&out->lock);
2157 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302158 }
2159 }
2160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002162 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002163 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002164 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2165 ret = voice_extn_compress_voip_start_output_stream(out);
2166 else
2167 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002168 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002171 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 goto exit;
2173 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002174 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2175 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002178 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002179 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002180 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002181 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002182 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2183 out->send_new_metadata = 0;
2184 }
2185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002186 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302187 if (ret < 0)
2188 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002189 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002190 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302191 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002192 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302193 } else if (-ENETRESET == ret) {
2194 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2195 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2196 pthread_mutex_unlock(&out->lock);
2197 out_standby(&out->stream.common);
2198 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302200 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002202 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002203 out->playback_started = 1;
2204 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002205
2206 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2207 popcount(out->channel_mask),
2208 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 }
2210 pthread_mutex_unlock(&out->lock);
2211 return ret;
2212 } else {
2213 if (out->pcm) {
2214 if (out->muted)
2215 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002217 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002218
2219 if (adev->adm_request_focus)
2220 adev->adm_request_focus(adev->adm_data, out->handle);
2221
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2223 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2224 else
2225 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002226
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302227 if (ret < 0)
2228 ret = -errno;
2229 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002230 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002231
2232 if (adev->adm_abandon_focus)
2233 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 }
2236
2237exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302238 /* ToDo: There may be a corner case when SSR happens back to back during
2239 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302240 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302241 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302242 }
2243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 pthread_mutex_unlock(&out->lock);
2245
2246 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002247 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002248 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302249 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302250 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302251 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302252 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302253 out->standby = true;
2254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002256 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302257 out_get_sample_rate(&out->stream.common));
2258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
2260 return bytes;
2261}
2262
2263static int out_get_render_position(const struct audio_stream_out *stream,
2264 uint32_t *dsp_frames)
2265{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302267 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002268
2269 if (dsp_frames == NULL)
2270 return -EINVAL;
2271
2272 *dsp_frames = 0;
2273 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002274 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 pthread_mutex_lock(&out->lock);
2276 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302277 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302279 if (ret < 0)
2280 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 ALOGVV("%s rendered frames %d sample_rate %d",
2282 __func__, *dsp_frames, out->sample_rate);
2283 }
2284 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302285 if (-ENETRESET == ret) {
2286 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2287 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2288 return -EINVAL;
2289 } else if(ret < 0) {
2290 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2291 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302292 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2293 /*
2294 * Handle corner case where compress session is closed during SSR
2295 * and timestamp is queried
2296 */
2297 ALOGE(" ERROR: sound card not active, return error");
2298 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302299 } else {
2300 return 0;
2301 }
Zhou Song32a556e2015-05-05 10:46:56 +08002302 } else if (audio_is_linear_pcm(out->format)) {
2303 *dsp_frames = out->written;
2304 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 } else
2306 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307}
2308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002309static int out_add_audio_effect(const struct audio_stream *stream __unused,
2310 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311{
2312 return 0;
2313}
2314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002315static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2316 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317{
2318 return 0;
2319}
2320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002321static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2322 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323{
2324 return -EINVAL;
2325}
2326
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002327static int out_get_presentation_position(const struct audio_stream_out *stream,
2328 uint64_t *frames, struct timespec *timestamp)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002332 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002333
2334 pthread_mutex_lock(&out->lock);
2335
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002336 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002337 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302338 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002339 &out->sample_rate);
2340 ALOGVV("%s rendered frames %ld sample_rate %d",
2341 __func__, dsp_frames, out->sample_rate);
2342 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302343 if (ret < 0)
2344 ret = -errno;
2345 if (-ENETRESET == ret) {
2346 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2347 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2348 ret = -EINVAL;
2349 } else
2350 ret = 0;
2351
Eric Laurent949a0892013-09-20 09:20:13 -07002352 /* this is the best we can do */
2353 clock_gettime(CLOCK_MONOTONIC, timestamp);
2354 }
2355 } else {
2356 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002357 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002358 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2359 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002360 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002361 // This adjustment accounts for buffering after app processor.
2362 // It is based on estimated DSP latency per use case, rather than exact.
2363 signed_frames -=
2364 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2365
Eric Laurent949a0892013-09-20 09:20:13 -07002366 // It would be unusual for this value to be negative, but check just in case ...
2367 if (signed_frames >= 0) {
2368 *frames = signed_frames;
2369 ret = 0;
2370 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002371 }
2372 }
2373 }
2374
2375 pthread_mutex_unlock(&out->lock);
2376
2377 return ret;
2378}
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380static int out_set_callback(struct audio_stream_out *stream,
2381 stream_callback_t callback, void *cookie)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384
2385 ALOGV("%s", __func__);
2386 pthread_mutex_lock(&out->lock);
2387 out->offload_callback = callback;
2388 out->offload_cookie = cookie;
2389 pthread_mutex_unlock(&out->lock);
2390 return 0;
2391}
2392
2393static int out_pause(struct audio_stream_out* stream)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 int status = -ENOSYS;
2397 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002398 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002399 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 pthread_mutex_lock(&out->lock);
2401 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302402 struct audio_device *adev = out->dev;
2403 int snd_scard_state = get_snd_card_state(adev);
2404
2405 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2406 status = compress_pause(out->compr);
2407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002409
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302410 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002411 audio_extn_dts_notify_playback_state(out->usecase, 0,
2412 out->sample_rate, popcount(out->channel_mask),
2413 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 }
2415 pthread_mutex_unlock(&out->lock);
2416 }
2417 return status;
2418}
2419
2420static int out_resume(struct audio_stream_out* stream)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423 int status = -ENOSYS;
2424 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002425 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002426 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 status = 0;
2428 pthread_mutex_lock(&out->lock);
2429 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302430 struct audio_device *adev = out->dev;
2431 int snd_scard_state = get_snd_card_state(adev);
2432
2433 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2434 status = compress_resume(out->compr);
2435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002437
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302438 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002439 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2440 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
2442 pthread_mutex_unlock(&out->lock);
2443 }
2444 return status;
2445}
2446
2447static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450 int status = -ENOSYS;
2451 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002452 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 pthread_mutex_lock(&out->lock);
2454 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2455 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2456 else
2457 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2458 pthread_mutex_unlock(&out->lock);
2459 }
2460 return status;
2461}
2462
2463static int out_flush(struct audio_stream_out* stream)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002467 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002468 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 pthread_mutex_lock(&out->lock);
2470 stop_compressed_output_l(out);
2471 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002472 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 return 0;
2474 }
2475 return -ENOSYS;
2476}
2477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478/** audio_stream_in implementation **/
2479static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2480{
2481 struct stream_in *in = (struct stream_in *)stream;
2482
2483 return in->config.rate;
2484}
2485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002486static int in_set_sample_rate(struct audio_stream *stream __unused,
2487 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488{
2489 return -ENOSYS;
2490}
2491
2492static size_t in_get_buffer_size(const struct audio_stream *stream)
2493{
2494 struct stream_in *in = (struct stream_in *)stream;
2495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2497 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002498 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2499 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002500
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002501 return in->config.period_size *
2502 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
2505static uint32_t in_get_channels(const struct audio_stream *stream)
2506{
2507 struct stream_in *in = (struct stream_in *)stream;
2508
2509 return in->channel_mask;
2510}
2511
2512static audio_format_t in_get_format(const struct audio_stream *stream)
2513{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002514 struct stream_in *in = (struct stream_in *)stream;
2515
2516 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517}
2518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002519static int in_set_format(struct audio_stream *stream __unused,
2520 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521{
2522 return -ENOSYS;
2523}
2524
2525static int in_standby(struct audio_stream *stream)
2526{
2527 struct stream_in *in = (struct stream_in *)stream;
2528 struct audio_device *adev = in->dev;
2529 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302530 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2531 stream, in->usecase, use_case_table[in->usecase]);
2532
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002533 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2534 /* Ignore standby in case of voip call because the voip input
2535 * stream is closed in adev_close_input_stream()
2536 */
2537 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2538 return status;
2539 }
2540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002542 if (!in->standby && in->is_st_session) {
2543 ALOGD("%s: sound trigger pcm stop lab", __func__);
2544 audio_extn_sound_trigger_stop_lab(in);
2545 in->standby = 1;
2546 }
2547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002549 if (adev->adm_deregister_stream)
2550 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2551
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002552 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 if (in->pcm) {
2555 pcm_close(in->pcm);
2556 in->pcm = NULL;
2557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002559 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 }
2561 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002562 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 return status;
2564}
2565
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002566static int in_dump(const struct audio_stream *stream __unused,
2567 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568{
2569 return 0;
2570}
2571
2572static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2573{
2574 struct stream_in *in = (struct stream_in *)stream;
2575 struct audio_device *adev = in->dev;
2576 struct str_parms *parms;
2577 char *str;
2578 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002579 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302581 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 parms = str_parms_create_str(kvpairs);
2583
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302584 if (!parms)
2585 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002587 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002588
2589 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2590 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 val = atoi(value);
2592 /* no audio source uses val == 0 */
2593 if ((in->source != val) && (val != 0)) {
2594 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002595 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2596 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2597 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2598 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002599 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002600 err = voice_extn_compress_voip_open_input_stream(in);
2601 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002602 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002603 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002604 }
2605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 }
2607 }
2608
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002609 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2610 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002612 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 in->device = val;
2614 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002615 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 }
2618 }
2619
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002620done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623
2624 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302625error:
Eric Laurent994a6932013-07-17 11:51:42 -07002626 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 return ret;
2628}
2629
2630static char* in_get_parameters(const struct audio_stream *stream,
2631 const char *keys)
2632{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002633 struct stream_in *in = (struct stream_in *)stream;
2634 struct str_parms *query = str_parms_create_str(keys);
2635 char *str;
2636 char value[256];
2637 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002638
2639 if (!query || !reply) {
2640 ALOGE("in_get_parameters: failed to create query or reply");
2641 return NULL;
2642 }
2643
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002644 ALOGV("%s: enter: keys - %s", __func__, keys);
2645
2646 voice_extn_in_get_parameters(in, query, reply);
2647
2648 str = str_parms_to_str(reply);
2649 str_parms_destroy(query);
2650 str_parms_destroy(reply);
2651
2652 ALOGV("%s: exit: returns - %s", __func__, str);
2653 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654}
2655
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002656static int in_set_gain(struct audio_stream_in *stream __unused,
2657 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658{
2659 return 0;
2660}
2661
2662static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2663 size_t bytes)
2664{
2665 struct stream_in *in = (struct stream_in *)stream;
2666 struct audio_device *adev = in->dev;
2667 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302668 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302671
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002672 if (in->is_st_session) {
2673 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2674 /* Read from sound trigger HAL */
2675 audio_extn_sound_trigger_read(in, buffer, bytes);
2676 pthread_mutex_unlock(&in->lock);
2677 return bytes;
2678 }
2679
2680 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2681 ALOGD(" %s: sound card is not active/SSR state", __func__);
2682 ret= -EIO;;
2683 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302684 }
2685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002687 pthread_mutex_lock(&adev->lock);
2688 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2689 ret = voice_extn_compress_voip_start_input_stream(in);
2690 else
2691 ret = start_input_stream(in);
2692 pthread_mutex_unlock(&adev->lock);
2693 if (ret != 0) {
2694 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
2696 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002697 if (adev->adm_register_input_stream)
2698 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002701 if (adev->adm_request_focus)
2702 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002705 if (audio_extn_ssr_get_enabled() &&
2706 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002707 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002708 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2709 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002710 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2711 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002712 else
2713 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302714 if (ret < 0)
2715 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 }
2717
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002718 if (adev->adm_abandon_focus)
2719 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 /*
2722 * Instead of writing zeroes here, we could trust the hardware
2723 * to always provide zeroes when muted.
2724 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302725 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2726 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 memset(buffer, 0, bytes);
2728
2729exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302730 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302731 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002732 if (-ENETRESET == ret)
2733 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 pthread_mutex_unlock(&in->lock);
2736
2737 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302738 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302739 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302740 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302741 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302742 in->standby = true;
2743 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302744 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002746 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002747 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302748 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 }
2750 return bytes;
2751}
2752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002753static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754{
2755 return 0;
2756}
2757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002758static int add_remove_audio_effect(const struct audio_stream *stream,
2759 effect_handle_t effect,
2760 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002762 struct stream_in *in = (struct stream_in *)stream;
2763 int status = 0;
2764 effect_descriptor_t desc;
2765
2766 status = (*effect)->get_descriptor(effect, &desc);
2767 if (status != 0)
2768 return status;
2769
2770 pthread_mutex_lock(&in->lock);
2771 pthread_mutex_lock(&in->dev->lock);
2772 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2773 in->enable_aec != enable &&
2774 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2775 in->enable_aec = enable;
2776 if (!in->standby)
2777 select_devices(in->dev, in->usecase);
2778 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002779 if (in->enable_ns != enable &&
2780 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2781 in->enable_ns = enable;
2782 if (!in->standby)
2783 select_devices(in->dev, in->usecase);
2784 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002785 pthread_mutex_unlock(&in->dev->lock);
2786 pthread_mutex_unlock(&in->lock);
2787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 return 0;
2789}
2790
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002791static int in_add_audio_effect(const struct audio_stream *stream,
2792 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793{
Eric Laurent994a6932013-07-17 11:51:42 -07002794 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002795 return add_remove_audio_effect(stream, effect, true);
2796}
2797
2798static int in_remove_audio_effect(const struct audio_stream *stream,
2799 effect_handle_t effect)
2800{
Eric Laurent994a6932013-07-17 11:51:42 -07002801 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002802 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803}
2804
2805static int adev_open_output_stream(struct audio_hw_device *dev,
2806 audio_io_handle_t handle,
2807 audio_devices_t devices,
2808 audio_output_flags_t flags,
2809 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002810 struct audio_stream_out **stream_out,
2811 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812{
2813 struct audio_device *adev = (struct audio_device *)dev;
2814 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002815 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002816 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302819
2820 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2821 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002822 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302823 return -EINVAL;
2824 }
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2827
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302828 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2829 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2830 devices, flags, &out->stream);
2831
2832
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002833 if (!out) {
2834 return -ENOMEM;
2835 }
2836
Haynes Mathew George204045b2015-02-25 20:32:03 -08002837 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2838 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 if (devices == AUDIO_DEVICE_NONE)
2841 devices = AUDIO_DEVICE_OUT_SPEAKER;
2842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843 out->flags = flags;
2844 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002845 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002846 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->sample_rate = config->sample_rate;
2848 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2849 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002850 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002851 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002852 out->non_blocking = 0;
2853 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854
2855 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002856 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2857 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002858 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2859 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2860
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002861 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002862 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2863 ret = read_hdmi_channel_masks(out);
2864
2865 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2866 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002867 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002868 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002869 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002870
2871 if (config->sample_rate == 0)
2872 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2873 if (config->channel_mask == 0)
2874 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2875
2876 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2879 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002881 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002883 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2884 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002885 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002886 ret = voice_extn_compress_voip_open_output_stream(out);
2887 if (ret != 0) {
2888 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2889 __func__, ret);
2890 goto error_open;
2891 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002892 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2893 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2896 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2897 ALOGE("%s: Unsupported Offload information", __func__);
2898 ret = -EINVAL;
2899 goto error_open;
2900 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002901
2902 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2903 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2904 ALOGV("read and update_pass through formats");
2905 ret = audio_extn_dolby_update_passt_formats(adev, out);
2906 if(ret != 0) {
2907 goto error_open;
2908 }
2909 if(config->offload_info.format == 0)
2910 config->offload_info.format = out->supported_formats[0];
2911 }
2912
Mingming Yin90310102013-11-13 16:57:00 -08002913 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002914 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002915 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 ret = -EINVAL;
2917 goto error_open;
2918 }
2919
2920 out->compr_config.codec = (struct snd_codec *)
2921 calloc(1, sizeof(struct snd_codec));
2922
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002923 if (!out->compr_config.codec) {
2924 ret = -ENOMEM;
2925 goto error_open;
2926 }
2927
vivek mehta0ea887a2015-08-26 14:01:20 -07002928 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2929 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2930 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2931 } else {
2932 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2933 out->usecase = get_offload_usecase(adev);
2934 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 if (config->offload_info.channel_mask)
2936 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002937 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002939 config->offload_info.channel_mask = config->channel_mask;
2940 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002941 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 out->sample_rate = config->offload_info.sample_rate;
2943
2944 out->stream.set_callback = out_set_callback;
2945 out->stream.pause = out_pause;
2946 out->stream.resume = out_resume;
2947 out->stream.drain = out_drain;
2948 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002949 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002951 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002952 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002953 audio_extn_dolby_get_snd_codec_id(adev, out,
2954 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002955 else
2956 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002958
2959 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2960 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002961 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002962 platform_get_pcm_offload_buffer_size(&config->offload_info);
2963 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2964 out->compr_config.fragment_size =
2965 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002966 } else {
2967 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002968 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002969 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2971 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002972 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 out->compr_config.codec->bit_rate =
2974 config->offload_info.bit_rate;
2975 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002976 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302978 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002979 /*TODO: Do we need to change it for passthrough */
2980 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981
Manish Dewangana6fc5442015-08-24 20:30:31 +05302982 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2983 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2984 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2985 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002986 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2987 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002988 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002989 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002990 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2991 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002992
Mingming Yin3ee55c62014-08-04 14:23:35 -07002993 if (out->bit_width == 24) {
2994 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2995 }
2996
Amit Shekhar6f461b12014-08-01 14:52:58 -07002997 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302998 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3001 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003002
Mingming Yin497419f2015-07-01 16:57:32 -07003003 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003004 //this flag is set from framework only if its for PCM formats
3005 //no need to check for PCM format again
3006 out->non_blocking = 0;
3007 out->use_small_bufs = true;
3008 ALOGI("Keep write blocking for small buff: non_blockling %d",
3009 out->non_blocking);
3010 }
3011
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003012 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003013 out->offload_state = OFFLOAD_STATE_IDLE;
3014 out->playback_started = 0;
3015
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003016 audio_extn_dts_create_state_notifier_node(out->usecase);
3017
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 create_offload_callback_thread(out);
3019 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3020 __func__, config->offload_info.version,
3021 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003022 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003023 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003024 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3025 ret = voice_check_and_set_incall_music_usecase(adev, out);
3026 if (ret != 0) {
3027 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3028 __func__, ret);
3029 goto error_open;
3030 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003031 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3032 if (config->sample_rate == 0)
3033 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3034 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3035 config->sample_rate != 8000) {
3036 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3037 ret = -EINVAL;
3038 goto error_open;
3039 }
3040 out->sample_rate = config->sample_rate;
3041 out->config.rate = config->sample_rate;
3042 if (config->format == AUDIO_FORMAT_DEFAULT)
3043 config->format = AUDIO_FORMAT_PCM_16_BIT;
3044 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3045 config->format = AUDIO_FORMAT_PCM_16_BIT;
3046 ret = -EINVAL;
3047 goto error_open;
3048 }
3049 out->format = config->format;
3050 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3051 out->config = pcm_config_afe_proxy_playback;
3052 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003053 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003054 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3056 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003058 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3059 format = AUDIO_FORMAT_PCM_16_BIT;
3060 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3061 out->config = pcm_config_deep_buffer;
3062 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003063 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003064 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003065 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003066 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003067 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003068 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 }
3070
Amit Shekhar1d896042014-10-03 13:16:09 -07003071 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3072 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003073 /* TODO remove this hardcoding and check why width is zero*/
3074 if (out->bit_width == 0)
3075 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003076 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3077 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003078 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003079 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003080 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3081 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3082 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003083 if(adev->primary_output == NULL)
3084 adev->primary_output = out;
3085 else {
3086 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003087 ret = -EEXIST;
3088 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003089 }
3090 }
3091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 /* Check if this usecase is already existing */
3093 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003094 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3095 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003098 ret = -EEXIST;
3099 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 }
3101 pthread_mutex_unlock(&adev->lock);
3102
3103 out->stream.common.get_sample_rate = out_get_sample_rate;
3104 out->stream.common.set_sample_rate = out_set_sample_rate;
3105 out->stream.common.get_buffer_size = out_get_buffer_size;
3106 out->stream.common.get_channels = out_get_channels;
3107 out->stream.common.get_format = out_get_format;
3108 out->stream.common.set_format = out_set_format;
3109 out->stream.common.standby = out_standby;
3110 out->stream.common.dump = out_dump;
3111 out->stream.common.set_parameters = out_set_parameters;
3112 out->stream.common.get_parameters = out_get_parameters;
3113 out->stream.common.add_audio_effect = out_add_audio_effect;
3114 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3115 out->stream.get_latency = out_get_latency;
3116 out->stream.set_volume = out_set_volume;
3117 out->stream.write = out_write;
3118 out->stream.get_render_position = out_get_render_position;
3119 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003120 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003123 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003124 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125
3126 config->format = out->stream.common.get_format(&out->stream.common);
3127 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3128 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3129
3130 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303131 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003132 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003133
3134 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3135 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3136 popcount(out->channel_mask), out->playback_started);
3137
Eric Laurent994a6932013-07-17 11:51:42 -07003138 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003140
3141error_open:
3142 free(out);
3143 *stream_out = NULL;
3144 ALOGD("%s: exit: ret %d", __func__, ret);
3145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146}
3147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003148static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 struct audio_stream_out *stream)
3150{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 struct stream_out *out = (struct stream_out *)stream;
3152 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003153 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303155 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3156
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003157 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303158 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003159 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303160 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003161 if(ret != 0)
3162 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3163 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003164 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003165 out_standby(&stream->common);
3166
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003167 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003168 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003170 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 if (out->compr_config.codec != NULL)
3172 free(out->compr_config.codec);
3173 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003174
3175 if (adev->voice_tx_output == out)
3176 adev->voice_tx_output = NULL;
3177
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 pthread_cond_destroy(&out->cond);
3179 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003181 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182}
3183
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003184static void close_compress_sessions(struct audio_device *adev)
3185{
Mingming Yin7b762e72015-03-04 13:47:32 -08003186 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303187 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003188 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003189 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303190
3191 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003192 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303193 if (is_offload_usecase(usecase->id)) {
3194 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003195 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3196 out = usecase->stream.out;
3197 pthread_mutex_unlock(&adev->lock);
3198 out_standby(&out->stream.common);
3199 pthread_mutex_lock(&adev->lock);
3200 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303201 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003202 }
3203 pthread_mutex_unlock(&adev->lock);
3204}
3205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3207{
3208 struct audio_device *adev = (struct audio_device *)dev;
3209 struct str_parms *parms;
3210 char *str;
3211 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003212 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003213 int ret;
3214 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003216 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303219 if (!parms)
3220 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003221 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3222 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303223 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303224 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303225 struct listnode *node;
3226 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303227 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303228 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003229 //close compress sessions on OFFLINE status
3230 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303231 } else if (strstr(snd_card_status, "ONLINE")) {
3232 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303233 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003234 //send dts hpx license if enabled
3235 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303236 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303237 }
3238
3239 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003240 status = voice_set_parameters(adev, parms);
3241 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003242 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003244 status = platform_set_parameters(adev->platform, parms);
3245 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003246 goto done;
3247
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3249 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003250 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3252 adev->bluetooth_nrec = true;
3253 else
3254 adev->bluetooth_nrec = false;
3255 }
3256
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003257 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3258 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3260 adev->screen_off = false;
3261 else
3262 adev->screen_off = true;
3263 }
3264
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003265 ret = str_parms_get_int(parms, "rotation", &val);
3266 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003267 bool reverse_speakers = false;
3268 switch(val) {
3269 // FIXME: note that the code below assumes that the speakers are in the correct placement
3270 // relative to the user when the device is rotated 90deg from its default rotation. This
3271 // assumption is device-specific, not platform-specific like this code.
3272 case 270:
3273 reverse_speakers = true;
3274 break;
3275 case 0:
3276 case 90:
3277 case 180:
3278 break;
3279 default:
3280 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003281 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003282 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003283 if (status == 0) {
3284 if (adev->speaker_lr_swap != reverse_speakers) {
3285 adev->speaker_lr_swap = reverse_speakers;
3286 // only update the selected device if there is active pcm playback
3287 struct audio_usecase *usecase;
3288 struct listnode *node;
3289 list_for_each(node, &adev->usecase_list) {
3290 usecase = node_to_item(node, struct audio_usecase, list);
3291 if (usecase->type == PCM_PLAYBACK) {
3292 select_devices(adev, usecase->id);
3293 break;
3294 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003295 }
3296 }
3297 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003298 }
3299
Mingming Yin514a8bc2014-07-29 15:22:21 -07003300 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3301 if (ret >= 0) {
3302 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3303 adev->bt_wb_speech_enabled = true;
3304 else
3305 adev->bt_wb_speech_enabled = false;
3306 }
3307
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003308 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3309 if (ret >= 0) {
3310 val = atoi(value);
3311 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3312 ALOGV("cache new edid");
3313 platform_cache_edid(adev->platform);
3314 }
3315 }
3316
3317 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3318 if (ret >= 0) {
3319 val = atoi(value);
3320 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3321 ALOGV("invalidate cached edid");
3322 platform_invalidate_edid(adev->platform);
3323 }
3324 }
3325
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003326 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003327
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003328done:
3329 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003330 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303331error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003332 ALOGV("%s: exit with code(%d)", __func__, status);
3333 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
3336static char* adev_get_parameters(const struct audio_hw_device *dev,
3337 const char *keys)
3338{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003339 struct audio_device *adev = (struct audio_device *)dev;
3340 struct str_parms *reply = str_parms_create();
3341 struct str_parms *query = str_parms_create_str(keys);
3342 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303343 char value[256] = {0};
3344 int ret = 0;
3345
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003346 if (!query || !reply) {
3347 ALOGE("adev_get_parameters: failed to create query or reply");
3348 return NULL;
3349 }
3350
Naresh Tannirud7205b62014-06-20 02:54:48 +05303351 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3352 sizeof(value));
3353 if (ret >=0) {
3354 int val = 1;
3355 pthread_mutex_lock(&adev->snd_card_status.lock);
3356 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3357 val = 0;
3358 pthread_mutex_unlock(&adev->snd_card_status.lock);
3359 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3360 goto exit;
3361 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003362
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003363 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003364 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003365 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003366 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303367 pthread_mutex_unlock(&adev->lock);
3368
Naresh Tannirud7205b62014-06-20 02:54:48 +05303369exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003370 str = str_parms_to_str(reply);
3371 str_parms_destroy(query);
3372 str_parms_destroy(reply);
3373
3374 ALOGV("%s: exit: returns - %s", __func__, str);
3375 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376}
3377
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003378static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379{
3380 return 0;
3381}
3382
3383static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3384{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003385 int ret;
3386 struct audio_device *adev = (struct audio_device *)dev;
3387 pthread_mutex_lock(&adev->lock);
3388 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003389 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003390 pthread_mutex_unlock(&adev->lock);
3391 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392}
3393
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003394static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3395 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396{
3397 return -ENOSYS;
3398}
3399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003400static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3401 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402{
3403 return -ENOSYS;
3404}
3405
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003406static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3407 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408{
3409 return -ENOSYS;
3410}
3411
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003412static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3413 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414{
3415 return -ENOSYS;
3416}
3417
3418static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3419{
3420 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 pthread_mutex_lock(&adev->lock);
3423 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003424 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003426 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3427 voice_is_in_call(adev)) {
3428 voice_stop_call(adev);
3429 adev->current_call_output = NULL;
3430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 }
3432 pthread_mutex_unlock(&adev->lock);
3433 return 0;
3434}
3435
3436static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3437{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003438 int ret;
3439
3440 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003441 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003442 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3443 pthread_mutex_unlock(&adev->lock);
3444
3445 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446}
3447
3448static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3449{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003450 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 return 0;
3452}
3453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003454static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 const struct audio_config *config)
3456{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003457 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003459 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3460 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461}
3462
3463static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003464 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 audio_devices_t devices,
3466 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003467 struct audio_stream_in **stream_in,
3468 audio_input_flags_t flags __unused,
3469 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003470 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471{
3472 struct audio_device *adev = (struct audio_device *)dev;
3473 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003474 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003475 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003476 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478 *stream_in = NULL;
3479 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3480 return -EINVAL;
3481
3482 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003483
3484 if (!in) {
3485 ALOGE("failed to allocate input stream");
3486 return -ENOMEM;
3487 }
3488
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303489 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003490 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3491 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003493 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 in->stream.common.get_sample_rate = in_get_sample_rate;
3496 in->stream.common.set_sample_rate = in_set_sample_rate;
3497 in->stream.common.get_buffer_size = in_get_buffer_size;
3498 in->stream.common.get_channels = in_get_channels;
3499 in->stream.common.get_format = in_get_format;
3500 in->stream.common.set_format = in_set_format;
3501 in->stream.common.standby = in_standby;
3502 in->stream.common.dump = in_dump;
3503 in->stream.common.set_parameters = in_set_parameters;
3504 in->stream.common.get_parameters = in_get_parameters;
3505 in->stream.common.add_audio_effect = in_add_audio_effect;
3506 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3507 in->stream.set_gain = in_set_gain;
3508 in->stream.read = in_read;
3509 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3510
3511 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003512 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 in->standby = 1;
3515 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003516 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003517 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518
3519 /* Update config params with the requested sample rate and channels */
3520 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003521 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3522 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3523 is_low_latency = true;
3524#if LOW_LATENCY_CAPTURE_USE_CASE
3525 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3526#endif
3527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003532 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303533 if (adev->mode != AUDIO_MODE_IN_CALL) {
3534 ret = -EINVAL;
3535 goto err_open;
3536 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003537 if (config->sample_rate == 0)
3538 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3539 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3540 config->sample_rate != 8000) {
3541 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3542 ret = -EINVAL;
3543 goto err_open;
3544 }
3545 if (config->format == AUDIO_FORMAT_DEFAULT)
3546 config->format = AUDIO_FORMAT_PCM_16_BIT;
3547 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3548 config->format = AUDIO_FORMAT_PCM_16_BIT;
3549 ret = -EINVAL;
3550 goto err_open;
3551 }
3552
3553 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3554 in->config = pcm_config_afe_proxy_record;
3555 in->config.channels = channel_count;
3556 in->config.rate = config->sample_rate;
3557 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003558 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003559 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003560 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3561 ret = -EINVAL;
3562 goto err_open;
3563 }
3564 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003565 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003566 }
Mingming Yine62d7842013-10-25 16:26:03 -07003567 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003568 audio_extn_compr_cap_format_supported(config->format) &&
3569 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003570 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003571 } else {
3572 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003574 buffer_size = get_input_buffer_size(config->sample_rate,
3575 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003576 channel_count,
3577 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003578 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003579 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3580 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3581 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3582 (in->config.rate == 8000 || in->config.rate == 16000) &&
3583 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3584 voice_extn_compress_voip_open_input_stream(in);
3585 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003588 /* This stream could be for sound trigger lab,
3589 get sound trigger pcm if present */
3590 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303591 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003594 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003595 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596
3597err_open:
3598 free(in);
3599 *stream_in = NULL;
3600 return ret;
3601}
3602
3603static void adev_close_input_stream(struct audio_hw_device *dev,
3604 struct audio_stream_in *stream)
3605{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003606 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003607 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303609
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303610 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003611
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303612 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003613 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303614
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003615 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303616 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003617 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303618 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003619 if (ret != 0)
3620 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3621 __func__, ret);
3622 } else
3623 in_standby(&stream->common);
3624
Mingming Yin7b762e72015-03-04 13:47:32 -08003625 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003626 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003627 audio_extn_ssr_deinit();
3628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
Mingming Yine62d7842013-10-25 16:26:03 -07003630 if(audio_extn_compr_cap_enabled() &&
3631 audio_extn_compr_cap_format_supported(in->config.format))
3632 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003633
3634 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 return;
3636}
3637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003638static int adev_dump(const audio_hw_device_t *device __unused,
3639 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640{
3641 return 0;
3642}
3643
3644static int adev_close(hw_device_t *device)
3645{
3646 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003647
3648 if (!adev)
3649 return 0;
3650
3651 pthread_mutex_lock(&adev_init_lock);
3652
3653 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003654 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003655 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003656 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003657 audio_route_free(adev->audio_route);
3658 free(adev->snd_dev_ref_cnt);
3659 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003660 if (adev->adm_deinit)
3661 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003662 free(device);
3663 adev = NULL;
3664 }
3665 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 return 0;
3668}
3669
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003670/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3671 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3672 * just that it _might_ work.
3673 */
3674static int period_size_is_plausible_for_low_latency(int period_size)
3675{
3676 switch (period_size) {
3677 case 160:
3678 case 240:
3679 case 320:
3680 case 480:
3681 return 1;
3682 default:
3683 return 0;
3684 }
3685}
3686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687static int adev_open(const hw_module_t *module, const char *name,
3688 hw_device_t **device)
3689{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003692 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3694
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003695 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003696 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003697 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003698 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003699 ALOGD("%s: returning existing instance of adev", __func__);
3700 ALOGD("%s: exit", __func__);
3701 pthread_mutex_unlock(&adev_init_lock);
3702 return 0;
3703 }
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 adev = calloc(1, sizeof(struct audio_device));
3706
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003707 if (!adev) {
3708 pthread_mutex_unlock(&adev_init_lock);
3709 return -ENOMEM;
3710 }
3711
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003712 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3715 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3716 adev->device.common.module = (struct hw_module_t *)module;
3717 adev->device.common.close = adev_close;
3718
3719 adev->device.init_check = adev_init_check;
3720 adev->device.set_voice_volume = adev_set_voice_volume;
3721 adev->device.set_master_volume = adev_set_master_volume;
3722 adev->device.get_master_volume = adev_get_master_volume;
3723 adev->device.set_master_mute = adev_set_master_mute;
3724 adev->device.get_master_mute = adev_get_master_mute;
3725 adev->device.set_mode = adev_set_mode;
3726 adev->device.set_mic_mute = adev_set_mic_mute;
3727 adev->device.get_mic_mute = adev_get_mic_mute;
3728 adev->device.set_parameters = adev_set_parameters;
3729 adev->device.get_parameters = adev_get_parameters;
3730 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3731 adev->device.open_output_stream = adev_open_output_stream;
3732 adev->device.close_output_stream = adev_close_output_stream;
3733 adev->device.open_input_stream = adev_open_input_stream;
3734 adev->device.close_input_stream = adev_close_input_stream;
3735 adev->device.dump = adev_dump;
3736
3737 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003739 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003740 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003743 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003744 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003745 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003746 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003747 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003748 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003749 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303750
3751 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3752 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003754 adev->platform = platform_init(adev);
3755 if (!adev->platform) {
3756 free(adev->snd_dev_ref_cnt);
3757 free(adev);
3758 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3759 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003760 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003761 return -EINVAL;
3762 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003763
Naresh Tanniru4c630392014-05-12 01:05:52 +05303764 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3765
Eric Laurentc4aef752013-09-12 17:45:53 -07003766 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3767 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3768 if (adev->visualizer_lib == NULL) {
3769 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3770 } else {
3771 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3772 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003773 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003774 "visualizer_hal_start_output");
3775 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003776 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003777 "visualizer_hal_stop_output");
3778 }
3779 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003780 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003781 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003782
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003783 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3784 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3785 if (adev->offload_effects_lib == NULL) {
3786 ALOGE("%s: DLOPEN failed for %s", __func__,
3787 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3788 } else {
3789 ALOGV("%s: DLOPEN successful for %s", __func__,
3790 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3791 adev->offload_effects_start_output =
3792 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3793 "offload_effects_bundle_hal_start_output");
3794 adev->offload_effects_stop_output =
3795 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3796 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003797 adev->offload_effects_set_hpx_state =
3798 (int (*)(bool))dlsym(adev->offload_effects_lib,
3799 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003800 }
3801 }
3802
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003803 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3804 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3805 if (adev->adm_lib == NULL) {
3806 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3807 } else {
3808 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3809 adev->adm_init = (adm_init_t)
3810 dlsym(adev->adm_lib, "adm_init");
3811 adev->adm_deinit = (adm_deinit_t)
3812 dlsym(adev->adm_lib, "adm_deinit");
3813 adev->adm_register_input_stream = (adm_register_input_stream_t)
3814 dlsym(adev->adm_lib, "adm_register_input_stream");
3815 adev->adm_register_output_stream = (adm_register_output_stream_t)
3816 dlsym(adev->adm_lib, "adm_register_output_stream");
3817 adev->adm_deregister_stream = (adm_deregister_stream_t)
3818 dlsym(adev->adm_lib, "adm_deregister_stream");
3819 adev->adm_request_focus = (adm_request_focus_t)
3820 dlsym(adev->adm_lib, "adm_request_focus");
3821 adev->adm_abandon_focus = (adm_abandon_focus_t)
3822 dlsym(adev->adm_lib, "adm_abandon_focus");
3823 }
3824 }
3825
Mingming Yin514a8bc2014-07-29 15:22:21 -07003826 adev->bt_wb_speech_enabled = false;
3827
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003828 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 *device = &adev->device.common;
3830
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003831 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3832 &adev->streams_output_cfg_list);
3833
Kiran Kandi910e1862013-10-29 13:29:42 -07003834 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003835
3836 char value[PROPERTY_VALUE_MAX];
3837 int trial;
3838 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3839 trial = atoi(value);
3840 if (period_size_is_plausible_for_low_latency(trial)) {
3841 pcm_config_low_latency.period_size = trial;
3842 pcm_config_low_latency.start_threshold = trial / 4;
3843 pcm_config_low_latency.avail_min = trial / 4;
3844 configured_low_latency_capture_period_size = trial;
3845 }
3846 }
3847 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3848 trial = atoi(value);
3849 if (period_size_is_plausible_for_low_latency(trial)) {
3850 configured_low_latency_capture_period_size = trial;
3851 }
3852 }
3853
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003854 pthread_mutex_unlock(&adev_init_lock);
3855
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003856 if (adev->adm_init)
3857 adev->adm_data = adev->adm_init();
3858
Eric Laurent994a6932013-07-17 11:51:42 -07003859 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 return 0;
3861}
3862
3863static struct hw_module_methods_t hal_module_methods = {
3864 .open = adev_open,
3865};
3866
3867struct audio_module HAL_MODULE_INFO_SYM = {
3868 .common = {
3869 .tag = HARDWARE_MODULE_TAG,
3870 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3871 .hal_api_version = HARDWARE_HAL_API_VERSION,
3872 .id = AUDIO_HARDWARE_MODULE_ID,
3873 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003874 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875 .methods = &hal_module_methods,
3876 },
3877};