blob: a8a84138ba4054120225e2c782f84648ef7a5c33 [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
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
vivek mehtaa76401a2015-04-24 14:12:15 -0700255__attribute__ ((visibility ("default")))
256bool audio_hw_send_gain_dep_calibration(int level) {
257 bool ret_val = false;
258 ALOGV("%s: called ... ", __func__);
259
260 pthread_mutex_lock(&adev_init_lock);
261
262 if (adev != NULL && adev->platform != NULL) {
263 pthread_mutex_lock(&adev->lock);
264 ret_val = platform_send_gain_dep_cal(adev->platform, level);
265 pthread_mutex_unlock(&adev->lock);
266 } else {
267 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
268 }
269
270 pthread_mutex_unlock(&adev_init_lock);
271
272 return ret_val;
273}
274
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800275static int check_and_set_gapless_mode(struct audio_device *adev) {
276
277
278 char value[PROPERTY_VALUE_MAX] = {0};
279 bool gapless_enabled = false;
280 const char *mixer_ctl_name = "Compress Gapless Playback";
281 struct mixer_ctl *ctl;
282
283 ALOGV("%s:", __func__);
284 property_get("audio.offload.gapless.enabled", value, NULL);
285 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
286
287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
288 if (!ctl) {
289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
290 __func__, mixer_ctl_name);
291 return -EINVAL;
292 }
293
294 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
295 ALOGE("%s: Could not set gapless mode %d",
296 __func__, gapless_enabled);
297 return -EINVAL;
298 }
299 return 0;
300}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700302static bool is_supported_format(audio_format_t format)
303{
Eric Laurent86e17132013-09-12 17:49:30 -0700304 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 format == AUDIO_FORMAT_AAC_LC ||
306 format == AUDIO_FORMAT_AAC_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800310 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530311 format == AUDIO_FORMAT_ALAC ||
312 format == AUDIO_FORMAT_APE ||
313 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_WMA ||
315 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800316 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317
318 return false;
319}
320
321static int get_snd_codec_id(audio_format_t format)
322{
323 int id = 0;
324
Ashish Jainf9b78162014-08-25 20:36:25 +0530325 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700326 case AUDIO_FORMAT_MP3:
327 id = SND_AUDIOCODEC_MP3;
328 break;
329 case AUDIO_FORMAT_AAC:
330 id = SND_AUDIOCODEC_AAC;
331 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800333 id = SND_AUDIOCODEC_PCM;
334 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700335 case AUDIO_FORMAT_FLAC:
336 id = SND_AUDIOCODEC_FLAC;
337 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530338 case AUDIO_FORMAT_ALAC:
339 id = SND_AUDIOCODEC_ALAC;
340 break;
341 case AUDIO_FORMAT_APE:
342 id = SND_AUDIOCODEC_APE;
343 break;
344 case AUDIO_FORMAT_VORBIS:
345 id = SND_AUDIOCODEC_VORBIS;
346 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800347 case AUDIO_FORMAT_WMA:
348 id = SND_AUDIOCODEC_WMA;
349 break;
350 case AUDIO_FORMAT_WMA_PRO:
351 id = SND_AUDIOCODEC_WMA_PRO;
352 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700353 default:
Mingming Yin90310102013-11-13 16:57:00 -0800354 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700355 }
356
357 return id;
358}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800359
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530360int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530361{
362 int snd_scard_state;
363
364 if (!adev)
365 return SND_CARD_STATE_OFFLINE;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 snd_scard_state = adev->snd_card_status.state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return snd_scard_state;
372}
373
374static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
375{
376 if (!adev)
377 return -ENOSYS;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700380 if (adev->snd_card_status.state != snd_scard_state) {
381 adev->snd_card_status.state = snd_scard_state;
382 platform_snd_card_update(adev->platform, snd_scard_state);
383 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530384 pthread_mutex_unlock(&adev->snd_card_status.lock);
385
386 return 0;
387}
388
Avinash Vaish71a8b972014-07-24 15:36:33 +0530389static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
390 struct audio_usecase *uc_info)
391{
392 struct listnode *node;
393 struct audio_usecase *usecase;
394
395 if (uc_info == NULL)
396 return -EINVAL;
397
398 /* Re-route all voice usecases on the shared backend other than the
399 specified usecase to new snd devices */
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800402 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530403 enable_audio_route(adev, usecase);
404 }
405 return 0;
406}
407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700408int pcm_ioctl(struct pcm *pcm, int request, ...)
409{
410 va_list ap;
411 void * arg;
412 int pcm_fd = *(int*)pcm;
413
414 va_start(ap, request);
415 arg = va_arg(ap, void *);
416 va_end(ap);
417
418 return ioctl(pcm_fd, request, arg);
419}
420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700421int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700422 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700425 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426
427 if (usecase == NULL)
428 return -EINVAL;
429
430 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
431
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800434 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800437#ifdef DS1_DOLBY_DAP_ENABLED
438 audio_extn_dolby_set_dmid(adev);
439 audio_extn_dolby_set_endpoint(adev);
440#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700441 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530443 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700444 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700445 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700448 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
449 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 ALOGV("%s: exit", __func__);
451 return 0;
452}
453
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700454int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700455 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530460 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461 return -EINVAL;
462
463 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 if (usecase->type == PCM_CAPTURE)
465 snd_device = usecase->in_snd_device;
466 else
467 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700469 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700470 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
471 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700472 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530473 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700478int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800483 if (snd_device < SND_DEVICE_MIN ||
484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800486 return -EINVAL;
487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
489 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490
491 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
492 ALOGE("%s: Invalid sound device returned", __func__);
493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700496 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 return 0;
499 }
500
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700501 if (audio_extn_spkr_prot_is_enabled())
502 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 /* start usb playback thread */
504 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
505 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
506 audio_extn_usb_start_playback(adev);
507
508 /* start usb capture thread */
509 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
510 audio_extn_usb_start_capture(adev);
511
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800512 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
513 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700514 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700515 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
516 adev->snd_dev_ref_cnt[snd_device]--;
517 return -EINVAL;
518 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200519 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800520 if (audio_extn_spkr_prot_start_processing(snd_device)) {
521 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200522 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 return -EINVAL;
524 }
525 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
527 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700528 /* due to the possibility of calibration overwrite between listen
529 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700530 audio_extn_sound_trigger_update_device_status(snd_device,
531 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530532 audio_extn_listen_update_device_status(snd_device,
533 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700534 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700535 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 return -EINVAL;
541 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300542 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700543 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 return 0;
546}
547
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700548int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700549 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800553 if (snd_device < SND_DEVICE_MIN ||
554 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800555 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 return -EINVAL;
557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
559 ALOGE("%s: device ref cnt is already 0", __func__);
560 return -EINVAL;
561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700571 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800573 /* exit usb play back thread */
574 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
575 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
576 audio_extn_usb_stop_playback();
577
578 /* exit usb capture thread */
579 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700580 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800581
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
583 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700584 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700585 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700589
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200590 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700591 audio_extn_sound_trigger_update_device_status(snd_device,
592 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530593 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800594 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 return 0;
598}
599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600static void check_usecases_codec_backend(struct audio_device *adev,
601 struct audio_usecase *uc_info,
602 snd_device_t snd_device)
603{
604 struct listnode *node;
605 struct audio_usecase *usecase;
606 bool switch_device[AUDIO_USECASE_MAX];
607 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800608 int backend_idx = DEFAULT_CODEC_BACKEND;
609 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
611 /*
612 * This function is to make sure that all the usecases that are active on
613 * the hardware codec backend are always routed to any one device that is
614 * handled by the hardware codec.
615 * For example, if low-latency and deep-buffer usecases are currently active
616 * on speaker and out_set_parameters(headset) is received on low-latency
617 * output, then we have to make sure deep-buffer is also switched to headset,
618 * because of the limitation that both the devices cannot be enabled
619 * at the same time as they share the same backend.
620 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700621 /*
622 * This call is to check if we need to force routing for a particular stream
623 * If there is a backend configuration change for the device when a
624 * new stream starts, then ADM needs to be closed and re-opened with the new
625 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800626 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800628 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
629 snd_device);
630 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800632 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800633 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 for (i = 0; i < AUDIO_USECASE_MAX; i++)
635 switch_device[i] = false;
636
637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639
640 if (usecase == uc_info)
641 continue;
642 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
643 ALOGV("%s: backend_idx: %d,"
644 "usecase_backend_idx: %d, curr device: %s, usecase device:"
645 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530646 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800647
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800648 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700649 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
651 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530652 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700654 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700655 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 switch_device[usecase->id] = true;
657 num_uc_to_switch++;
658 }
659 }
660
661 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700662 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530664 /* Make sure the previous devices to be disabled first and then enable the
665 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
668 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
675 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700677 }
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 /* Re-route all the usecases on the shared backend other than the
681 specified usecase to new snd devices */
682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530684 /* Update the out_snd_device only for the usecases that are enabled here */
685 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
686 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530687 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 }
689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690 }
691}
692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693static void check_and_route_capture_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info,
695 snd_device_t snd_device)
696{
697 struct listnode *node;
698 struct audio_usecase *usecase;
699 bool switch_device[AUDIO_USECASE_MAX];
700 int i, num_uc_to_switch = 0;
701
702 /*
703 * This function is to make sure that all the active capture usecases
704 * are always routed to the same input sound device.
705 * For example, if audio-record and voice-call usecases are currently
706 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
707 * is received for voice call then we have to make sure that audio-record
708 * usecase is also switched to earpiece i.e. voice-dmic-ef,
709 * because of the limitation that two devices cannot be enabled
710 * at the same time if they share the same backend.
711 */
712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
713 switch_device[i] = false;
714
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700719 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700720 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
721 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700722 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700723 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
724 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700725 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 switch_device[usecase->id] = true;
728 num_uc_to_switch++;
729 }
730 }
731
732 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700733 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530735 /* Make sure the previous devices to be disabled first and then enable the
736 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800741 }
742 }
743
744 list_for_each(node, &adev->usecase_list) {
745 usecase = node_to_item(node, struct audio_usecase, list);
746 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 }
749 }
750
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 /* Re-route all the usecases on the shared backend other than the
752 specified usecase to new snd devices */
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 /* Update the in_snd_device only before enabling the audio route */
756 if (switch_device[usecase->id] ) {
757 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800758 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530759 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763}
764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700766static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700768 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700769 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770
771 switch (channels) {
772 /*
773 * Do not handle stereo output in Multi-channel cases
774 * Stereo case is handled in normal playback path
775 */
776 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 break;
784 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700785 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700794 ALOGE("HDMI does not support multi channel playback");
795 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796 break;
797 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700798 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799}
800
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800801audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
802 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800809 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700810 ALOGV("%s: usecase id %d", __func__, usecase->id);
811 return usecase->id;
812 }
813 }
814 return USECASE_INVALID;
815}
816
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700817struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
825 if (usecase->id == uc_id)
826 return usecase;
827 }
828 return NULL;
829}
830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700831int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800833 snd_device_t out_snd_device = SND_DEVICE_NONE;
834 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 struct audio_usecase *usecase = NULL;
836 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800837 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800838 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800839 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800840 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 usecase = get_usecase_from_list(adev, uc_id);
844 if (usecase == NULL) {
845 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
846 return -EINVAL;
847 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800850 (usecase->type == VOIP_CALL) ||
851 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700852 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800853 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700854 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase->devices = usecase->stream.out->devices;
856 } else {
857 /*
858 * If the voice call is active, use the sound devices of voice call usecase
859 * so that it would not result any device switch. All the usecases will
860 * be switched to new device when select_devices() is called for voice call
861 * usecase. This is to avoid switching devices for voice call when
862 * check_usecases_codec_backend() is called below.
863 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700864 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700865 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800866 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
868 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 in_snd_device = vc_usecase->in_snd_device;
870 out_snd_device = vc_usecase->out_snd_device;
871 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800872 } else if (voice_extn_compress_voip_is_active(adev)) {
873 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700874 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530875 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 in_snd_device = voip_usecase->in_snd_device;
878 out_snd_device = voip_usecase->out_snd_device;
879 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800880 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800881 hfp_ucid = audio_extn_hfp_get_usecase();
882 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800884 in_snd_device = hfp_usecase->in_snd_device;
885 out_snd_device = hfp_usecase->out_snd_device;
886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 }
888 if (usecase->type == PCM_PLAYBACK) {
889 usecase->devices = usecase->stream.out->devices;
890 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700892 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800893 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700894 if (usecase->stream.out == adev->primary_output &&
895 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800896 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 select_devices(adev, adev->active_input->usecase);
898 }
899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 } else if (usecase->type == PCM_CAPTURE) {
901 usecase->devices = usecase->stream.in->device;
902 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700904 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530905 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
906 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
907 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
908 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700909 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
912 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700914 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 }
917 }
918
919 if (out_snd_device == usecase->out_snd_device &&
920 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922 }
923
sangwoobc677242013-08-08 16:53:43 +0900924 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700925 out_snd_device, platform_get_snd_device_name(out_snd_device),
926 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 /*
929 * Limitation: While in call, to do a device switch we need to disable
930 * and enable both RX and TX devices though one of them is same as current
931 * device.
932 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700933 if ((usecase->type == VOICE_CALL) &&
934 (usecase->in_snd_device != SND_DEVICE_NONE) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700937 }
938
939 if (((usecase->type == VOICE_CALL) ||
940 (usecase->type == VOIP_CALL)) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
942 /* Disable sidetone only if voice/voip call already exists */
943 if (voice_is_call_state_active(adev) ||
944 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700945 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 /* Disable current sound devices */
949 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700950 disable_audio_route(adev, usecase);
951 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700955 disable_audio_route(adev, usecase);
956 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957 }
958
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800959 /* Applicable only on the targets that has external modem.
960 * New device information should be sent to modem before enabling
961 * the devices to reduce in-call device switch time.
962 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 if ((usecase->type == VOICE_CALL) &&
964 (usecase->in_snd_device != SND_DEVICE_NONE) &&
965 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800966 status = platform_switch_voice_call_enable_device_config(adev->platform,
967 out_snd_device,
968 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700969 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Enable new sound devices */
972 if (out_snd_device != SND_DEVICE_NONE) {
973 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
974 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700975 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976 }
977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700978 if (in_snd_device != SND_DEVICE_NONE) {
979 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700981 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982
Avinash Vaish71a8b972014-07-24 15:36:33 +0530983 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700984 status = platform_switch_voice_call_device_post(adev->platform,
985 out_snd_device,
986 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530987 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700988 /* Enable sidetone only if voice/voip call already exists */
989 if (voice_is_call_state_active(adev) ||
990 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700991 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800993
sangwoo170731f2013-06-08 15:36:36 +0900994 usecase->in_snd_device = in_snd_device;
995 usecase->out_snd_device = out_snd_device;
996
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530997 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700998 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530999 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 usecase->stream.out->flags,
1002 usecase->stream.out->format,
1003 usecase->stream.out->sample_rate,
1004 usecase->stream.out->bit_width,
1005 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001006 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301007 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001008
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001009 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001010
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001011 /* Applicable only on the targets that has external modem.
1012 * Enable device command should be sent to modem only after
1013 * enabling voice call mixer controls
1014 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001015 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001016 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1017 out_snd_device,
1018 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301019 ALOGD("%s: done",__func__);
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 return status;
1022}
1023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024static int stop_input_stream(struct stream_in *in)
1025{
1026 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 struct audio_usecase *uc_info;
1028 struct audio_device *adev = in->dev;
1029
Eric Laurentc8400632013-02-14 19:04:54 -08001030 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031
Eric Laurent994a6932013-07-17 11:51:42 -07001032 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 uc_info = get_usecase_from_list(adev, in->usecase);
1035 if (uc_info == NULL) {
1036 ALOGE("%s: Could not find the usecase (%d) in the list",
1037 __func__, in->usecase);
1038 return -EINVAL;
1039 }
1040
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001041 /* Close in-call recording streams */
1042 voice_check_and_stop_incall_rec_usecase(adev, in);
1043
Eric Laurent150dbfe2013-02-27 14:31:02 -08001044 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001045 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046
1047 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001048 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001050 list_remove(&uc_info->list);
1051 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052
Eric Laurent994a6932013-07-17 11:51:42 -07001053 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 return ret;
1055}
1056
1057int start_input_stream(struct stream_in *in)
1058{
1059 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 struct audio_usecase *uc_info;
1062 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301063 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Mingming Yine62d7842013-10-25 16:26:03 -07001065 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301066 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1067 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001068
Naresh Tanniru80659832014-06-04 18:17:56 +05301069
1070 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301071 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301072 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301073 goto error_config;
1074 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301075
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001076 /* Check if source matches incall recording usecase criteria */
1077 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1078 if (ret)
1079 goto error_config;
1080 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001081 ALOGD("%s: Updated usecase(%d: %s)",
1082 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001083
Eric Laurentb23d5282013-05-14 15:27:20 -07001084 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 if (in->pcm_device_id < 0) {
1086 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1087 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001088 ret = -EINVAL;
1089 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091
1092 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001094
1095 if (!uc_info) {
1096 ret = -ENOMEM;
1097 goto error_config;
1098 }
1099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 uc_info->id = in->usecase;
1101 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001102 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 uc_info->devices = in->device;
1104 uc_info->in_snd_device = SND_DEVICE_NONE;
1105 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001107 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301108 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110
Eric Laurentc8400632013-02-14 19:04:54 -08001111 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001112 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1113
1114 unsigned int flags = PCM_IN;
1115 unsigned int pcm_open_retry_count = 0;
1116
1117 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1118 flags |= PCM_MMAP | PCM_NOIRQ;
1119 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1120 }
1121
1122 while (1) {
1123 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1124 flags, &in->config);
1125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1126 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1127 if (in->pcm != NULL) {
1128 pcm_close(in->pcm);
1129 in->pcm = NULL;
1130 }
1131 if (pcm_open_retry_count-- == 0) {
1132 ret = -EIO;
1133 goto error_open;
1134 }
1135 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1136 continue;
1137 }
1138 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301140 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301141
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001142 ALOGV("%s: pcm_prepare start", __func__);
1143 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001144 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001145
Eric Laurentc8400632013-02-14 19:04:54 -08001146 return ret;
1147
1148error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301150 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001151
1152error_config:
1153 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001155
1156 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157}
1158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001159/* must be called with out->lock locked */
1160static int send_offload_cmd_l(struct stream_out* out, int command)
1161{
1162 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1163
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001164 if (!cmd) {
1165 ALOGE("failed to allocate mem for command 0x%x", command);
1166 return -ENOMEM;
1167 }
1168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001169 ALOGVV("%s %d", __func__, command);
1170
1171 cmd->cmd = command;
1172 list_add_tail(&out->offload_cmd_list, &cmd->node);
1173 pthread_cond_signal(&out->offload_cond);
1174 return 0;
1175}
1176
1177/* must be called iwth out->lock locked */
1178static void stop_compressed_output_l(struct stream_out *out)
1179{
1180 out->offload_state = OFFLOAD_STATE_IDLE;
1181 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001182 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001183 if (out->compr != NULL) {
1184 compress_stop(out->compr);
1185 while (out->offload_thread_blocked) {
1186 pthread_cond_wait(&out->cond, &out->lock);
1187 }
1188 }
1189}
1190
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001191bool is_offload_usecase(audio_usecase_t uc_id)
1192{
1193 unsigned int i;
1194 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1195 if (uc_id == offload_usecases[i])
1196 return true;
1197 }
1198 return false;
1199}
1200
1201static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1202{
1203 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1204 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1205 char value[PROPERTY_VALUE_MAX] = {0};
1206
1207 property_get("audio.offload.multiple.enabled", value, NULL);
1208 if (!(atoi(value) || !strncmp("true", value, 4)))
1209 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1210
1211 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1212 for (i = 0; i < num_usecase; i++) {
1213 if (!(adev->offload_usecases_state & (0x1<<i))) {
1214 adev->offload_usecases_state |= 0x1 << i;
1215 ret = offload_usecases[i];
1216 break;
1217 }
1218 }
1219 ALOGV("%s: offload usecase is %d", __func__, ret);
1220 return ret;
1221}
1222
1223static void free_offload_usecase(struct audio_device *adev,
1224 audio_usecase_t uc_id)
1225{
1226 unsigned int i;
1227 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1228 if (offload_usecases[i] == uc_id) {
1229 adev->offload_usecases_state &= ~(0x1<<i);
1230 break;
1231 }
1232 }
1233 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1234}
1235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001236static void *offload_thread_loop(void *context)
1237{
1238 struct stream_out *out = (struct stream_out *) context;
1239 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001240 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001242 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1243 set_sched_policy(0, SP_FOREGROUND);
1244 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1245
1246 ALOGV("%s", __func__);
1247 pthread_mutex_lock(&out->lock);
1248 for (;;) {
1249 struct offload_cmd *cmd = NULL;
1250 stream_callback_event_t event;
1251 bool send_callback = false;
1252
1253 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1254 __func__, list_empty(&out->offload_cmd_list),
1255 out->offload_state);
1256 if (list_empty(&out->offload_cmd_list)) {
1257 ALOGV("%s SLEEPING", __func__);
1258 pthread_cond_wait(&out->offload_cond, &out->lock);
1259 ALOGV("%s RUNNING", __func__);
1260 continue;
1261 }
1262
1263 item = list_head(&out->offload_cmd_list);
1264 cmd = node_to_item(item, struct offload_cmd, node);
1265 list_remove(item);
1266
1267 ALOGVV("%s STATE %d CMD %d out->compr %p",
1268 __func__, out->offload_state, cmd->cmd, out->compr);
1269
1270 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1271 free(cmd);
1272 break;
1273 }
1274
1275 if (out->compr == NULL) {
1276 ALOGE("%s: Compress handle is NULL", __func__);
1277 pthread_cond_signal(&out->cond);
1278 continue;
1279 }
1280 out->offload_thread_blocked = true;
1281 pthread_mutex_unlock(&out->lock);
1282 send_callback = false;
1283 switch(cmd->cmd) {
1284 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001286 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001287 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001288 send_callback = true;
1289 event = STREAM_CBK_EVENT_WRITE_READY;
1290 break;
1291 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001292 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301293 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001294 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301295 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001296 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301297 if (ret < 0)
1298 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301299 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301300 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001301 compress_drain(out->compr);
1302 else
1303 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301304 if (ret != -ENETRESET) {
1305 send_callback = true;
1306 event = STREAM_CBK_EVENT_DRAIN_READY;
1307 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1308 } else
1309 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 break;
1311 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001312 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001314 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 send_callback = true;
1316 event = STREAM_CBK_EVENT_DRAIN_READY;
1317 break;
1318 default:
1319 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1320 break;
1321 }
1322 pthread_mutex_lock(&out->lock);
1323 out->offload_thread_blocked = false;
1324 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001325 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001326 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001327 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001328 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 free(cmd);
1330 }
1331
1332 pthread_cond_signal(&out->cond);
1333 while (!list_empty(&out->offload_cmd_list)) {
1334 item = list_head(&out->offload_cmd_list);
1335 list_remove(item);
1336 free(node_to_item(item, struct offload_cmd, node));
1337 }
1338 pthread_mutex_unlock(&out->lock);
1339
1340 return NULL;
1341}
1342
1343static int create_offload_callback_thread(struct stream_out *out)
1344{
1345 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1346 list_init(&out->offload_cmd_list);
1347 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1348 offload_thread_loop, out);
1349 return 0;
1350}
1351
1352static int destroy_offload_callback_thread(struct stream_out *out)
1353{
1354 pthread_mutex_lock(&out->lock);
1355 stop_compressed_output_l(out);
1356 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1357
1358 pthread_mutex_unlock(&out->lock);
1359 pthread_join(out->offload_thread, (void **) NULL);
1360 pthread_cond_destroy(&out->offload_cond);
1361
1362 return 0;
1363}
1364
Eric Laurent07eeafd2013-10-06 12:52:49 -07001365static bool allow_hdmi_channel_config(struct audio_device *adev)
1366{
1367 struct listnode *node;
1368 struct audio_usecase *usecase;
1369 bool ret = true;
1370
1371 list_for_each(node, &adev->usecase_list) {
1372 usecase = node_to_item(node, struct audio_usecase, list);
1373 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1374 /*
1375 * If voice call is already existing, do not proceed further to avoid
1376 * disabling/enabling both RX and TX devices, CSD calls, etc.
1377 * Once the voice call done, the HDMI channels can be configured to
1378 * max channels of remaining use cases.
1379 */
1380 if (usecase->id == USECASE_VOICE_CALL) {
1381 ALOGD("%s: voice call is active, no change in HDMI channels",
1382 __func__);
1383 ret = false;
1384 break;
1385 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1386 ALOGD("%s: multi channel playback is active, "
1387 "no change in HDMI channels", __func__);
1388 ret = false;
1389 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001390 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001391 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001392 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1393 ", no change in HDMI channels", __func__,
1394 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001395 ret = false;
1396 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397 }
1398 }
1399 }
1400 return ret;
1401}
1402
1403static int check_and_set_hdmi_channels(struct audio_device *adev,
1404 unsigned int channels)
1405{
1406 struct listnode *node;
1407 struct audio_usecase *usecase;
1408
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001409 unsigned int supported_channels = platform_edid_get_max_channels(
1410 adev->platform);
1411 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001412 /* Check if change in HDMI channel config is allowed */
1413 if (!allow_hdmi_channel_config(adev))
1414 return 0;
1415
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001416 if (channels > supported_channels)
1417 channels = supported_channels;
1418
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001420 ALOGD("%s: Requested channels are same as current channels(%d)",
1421 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001422 return 0;
1423 }
1424
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001425 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001426 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001427 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428 adev->cur_hdmi_channels = channels;
1429
1430 /*
1431 * Deroute all the playback streams routed to HDMI so that
1432 * the back end is deactivated. Note that backend will not
1433 * be deactivated if any one stream is connected to it.
1434 */
1435 list_for_each(node, &adev->usecase_list) {
1436 usecase = node_to_item(node, struct audio_usecase, list);
1437 if (usecase->type == PCM_PLAYBACK &&
1438 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001439 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001440 }
1441 }
1442
1443 /*
1444 * Enable all the streams disabled above. Now the HDMI backend
1445 * will be activated with new channel configuration
1446 */
1447 list_for_each(node, &adev->usecase_list) {
1448 usecase = node_to_item(node, struct audio_usecase, list);
1449 if (usecase->type == PCM_PLAYBACK &&
1450 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001451 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001452 }
1453 }
1454
1455 return 0;
1456}
1457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458static int stop_output_stream(struct stream_out *out)
1459{
1460 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461 struct audio_usecase *uc_info;
1462 struct audio_device *adev = out->dev;
1463
Eric Laurent994a6932013-07-17 11:51:42 -07001464 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466 uc_info = get_usecase_from_list(adev, out->usecase);
1467 if (uc_info == NULL) {
1468 ALOGE("%s: Could not find the usecase (%d) in the list",
1469 __func__, out->usecase);
1470 return -EINVAL;
1471 }
1472
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001473 if (is_offload_usecase(out->usecase) &&
1474 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001475 if (adev->visualizer_stop_output != NULL)
1476 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001477
1478 audio_extn_dts_remove_state_notifier_node(out->usecase);
1479
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001480 if (adev->offload_effects_stop_output != NULL)
1481 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1482 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001483
Eric Laurent150dbfe2013-02-27 14:31:02 -08001484 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001485 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486
1487 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001488 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001490 list_remove(&uc_info->list);
1491 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001493 if (is_offload_usecase(out->usecase) &&
1494 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1495 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1496 ALOGV("Disable passthrough , reset mixer to pcm");
1497 /* NO_PASSTHROUGH */
1498 out->compr_config.codec->compr_passthr = 0;
1499 audio_extn_dolby_set_hdmi_config(adev, out);
1500 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1501 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001502 /* Must be called after removing the usecase from list */
1503 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1504 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1505
Eric Laurent994a6932013-07-17 11:51:42 -07001506 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 return ret;
1508}
1509
1510int start_output_stream(struct stream_out *out)
1511{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001513 int sink_channels = 0;
1514 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 struct audio_usecase *uc_info;
1516 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301517 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001519 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1520 ret = -EINVAL;
1521 goto error_config;
1522 }
1523
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301524 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1525 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1526 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301527
Naresh Tanniru80659832014-06-04 18:17:56 +05301528 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301529 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301530 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301531 goto error_config;
1532 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301533
Eric Laurentb23d5282013-05-14 15:27:20 -07001534 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 if (out->pcm_device_id < 0) {
1536 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1537 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001538 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001539 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 }
1541
1542 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001543
1544 if (!uc_info) {
1545 ret = -ENOMEM;
1546 goto error_config;
1547 }
1548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 uc_info->id = out->usecase;
1550 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001551 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 uc_info->devices = out->devices;
1553 uc_info->in_snd_device = SND_DEVICE_NONE;
1554 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001555 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001556 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001557 if (is_offload_usecase(out->usecase)) {
1558 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001559 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1560 }
1561 }
Mingming Yin9c041392014-05-01 15:37:31 -07001562 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1563 if (!strncmp("true", prop_value, 4)) {
1564 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001565 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1566 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001567 check_and_set_hdmi_channels(adev, sink_channels);
1568 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001569 if (is_offload_usecase(out->usecase)) {
1570 unsigned int ch_count = out->compr_config.codec->ch_in;
1571 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1572 /* backend channel config for passthrough stream is stereo */
1573 ch_count = 2;
1574 check_and_set_hdmi_channels(adev, ch_count);
1575 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001576 check_and_set_hdmi_channels(adev, out->config.channels);
1577 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001578 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001579 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001580 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 select_devices(adev, out->usecase);
1583
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1585 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001586 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001587 unsigned int flags = PCM_OUT;
1588 unsigned int pcm_open_retry_count = 0;
1589 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1590 flags |= PCM_MMAP | PCM_NOIRQ;
1591 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1592 } else
1593 flags |= PCM_MONOTONIC;
1594
1595 while (1) {
1596 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1597 flags, &out->config);
1598 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1599 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1600 if (out->pcm != NULL) {
1601 pcm_close(out->pcm);
1602 out->pcm = NULL;
1603 }
1604 if (pcm_open_retry_count-- == 0) {
1605 ret = -EIO;
1606 goto error_open;
1607 }
1608 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1609 continue;
1610 }
1611 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001613
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001614 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1615 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001616
1617 ALOGV("%s: pcm_prepare start", __func__);
1618 if (pcm_is_ready(out->pcm))
1619 pcm_prepare(out->pcm);
1620
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001621 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001622 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1623 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001625 out->compr = compress_open(adev->snd_card,
1626 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001627 COMPRESS_IN, &out->compr_config);
1628 if (out->compr && !is_compress_ready(out->compr)) {
1629 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1630 compress_close(out->compr);
1631 out->compr = NULL;
1632 ret = -EIO;
1633 goto error_open;
1634 }
1635 if (out->offload_callback)
1636 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001637
Fred Oh3f43e742015-03-04 18:42:34 -08001638 /* Since small bufs uses blocking writes, a write will be blocked
1639 for the default max poll time (20s) in the event of an SSR.
1640 Reduce the poll time to observe and deal with SSR faster.
1641 */
1642 if (out->use_small_bufs) {
1643 compress_set_max_poll_wait(out->compr, 1000);
1644 }
1645
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001646 audio_extn_dts_create_state_notifier_node(out->usecase);
1647 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1648 popcount(out->channel_mask),
1649 out->playback_started);
1650
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001651#ifdef DS1_DOLBY_DDP_ENABLED
1652 if (audio_extn_is_dolby_format(out->format))
1653 audio_extn_dolby_send_ddp_endp_params(adev);
1654#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001655 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1656 if (adev->visualizer_start_output != NULL)
1657 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1658 if (adev->offload_effects_start_output != NULL)
1659 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001660 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001663
Eric Laurent994a6932013-07-17 11:51:42 -07001664 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001669error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001670 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671}
1672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673static int check_input_parameters(uint32_t sample_rate,
1674 audio_format_t format,
1675 int channel_count)
1676{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001677 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001679 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001680 !voice_extn_compress_voip_is_format_supported(format) &&
1681 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001682
1683 switch (channel_count) {
1684 case 1:
1685 case 2:
1686 case 6:
1687 break;
1688 default:
1689 ret = -EINVAL;
1690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691
1692 switch (sample_rate) {
1693 case 8000:
1694 case 11025:
1695 case 12000:
1696 case 16000:
1697 case 22050:
1698 case 24000:
1699 case 32000:
1700 case 44100:
1701 case 48000:
1702 break;
1703 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001704 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 }
1706
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001707 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708}
1709
1710static size_t get_input_buffer_size(uint32_t sample_rate,
1711 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001712 int channel_count,
1713 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714{
1715 size_t size = 0;
1716
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001717 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1718 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001720 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001721 if (is_low_latency)
1722 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001723 /* ToDo: should use frame_size computed based on the format and
1724 channel_count here. */
1725 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001727 /* make sure the size is multiple of 32 bytes
1728 * At 48 kHz mono 16-bit PCM:
1729 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1730 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1731 */
1732 size += 0x1f;
1733 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001734
1735 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736}
1737
1738static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1739{
1740 struct stream_out *out = (struct stream_out *)stream;
1741
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743}
1744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001745static int out_set_sample_rate(struct audio_stream *stream __unused,
1746 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747{
1748 return -ENOSYS;
1749}
1750
1751static size_t out_get_buffer_size(const struct audio_stream *stream)
1752{
1753 struct stream_out *out = (struct stream_out *)stream;
1754
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001755 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001757 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1758 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001760 return out->config.period_size *
1761 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762}
1763
1764static uint32_t out_get_channels(const struct audio_stream *stream)
1765{
1766 struct stream_out *out = (struct stream_out *)stream;
1767
1768 return out->channel_mask;
1769}
1770
1771static audio_format_t out_get_format(const struct audio_stream *stream)
1772{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 struct stream_out *out = (struct stream_out *)stream;
1774
1775 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776}
1777
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001778static int out_set_format(struct audio_stream *stream __unused,
1779 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780{
1781 return -ENOSYS;
1782}
1783
1784static int out_standby(struct audio_stream *stream)
1785{
1786 struct stream_out *out = (struct stream_out *)stream;
1787 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301789 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1790 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001791 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1792 /* Ignore standby in case of voip call because the voip output
1793 * stream is closed in adev_close_output_stream()
1794 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301795 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001796 return 0;
1797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001801 if (adev->adm_deregister_stream)
1802 adev->adm_deregister_stream(adev->adm_data, out->handle);
1803
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001804 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001806 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->pcm) {
1808 pcm_close(out->pcm);
1809 out->pcm = NULL;
1810 }
1811 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001812 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001813 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 out->gapless_mdata.encoder_delay = 0;
1815 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001816 if (out->compr != NULL) {
1817 compress_close(out->compr);
1818 out->compr = NULL;
1819 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001822 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 }
1824 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001825 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 return 0;
1827}
1828
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001829static int out_dump(const struct audio_stream *stream __unused,
1830 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831{
1832 return 0;
1833}
1834
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1836{
1837 int ret = 0;
1838 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001839 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001840
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001841 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001842 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843 return -EINVAL;
1844 }
1845
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001846 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1847 if (ret >= 0) {
1848 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1849 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1850 ALOGV("ADTS format is set in offload mode");
1851 }
1852 out->send_new_metadata = 1;
1853 }
1854
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301855 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001856
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1858 if(ret >= 0)
1859 is_meta_data_params = true;
1860 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301861 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001862 is_meta_data_params = true;
1863 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301864 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001865 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1867 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001868 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301869 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1872 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001873 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301874 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001875 }
1876
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001877 if(!is_meta_data_params) {
1878 ALOGV("%s: Not gapless meta data params", __func__);
1879 return 0;
1880 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001881 out->send_new_metadata = 1;
1882 ALOGV("%s new encoder delay %u and padding %u", __func__,
1883 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1884
1885 return 0;
1886}
1887
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001888static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1889{
1890 return out == adev->primary_output || out == adev->voice_tx_output;
1891}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1894{
1895 struct stream_out *out = (struct stream_out *)stream;
1896 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001897 struct audio_usecase *usecase;
1898 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899 struct str_parms *parms;
1900 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001901 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001902 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903
sangwoobc677242013-08-08 16:53:43 +09001904 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301907 if (!parms)
1908 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001909 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1910 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001913 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001915 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301916 * When HDMI cable is unplugged/usb hs is disconnected the
1917 * music playback is paused and the policy manager sends routing=0
1918 * But the audioflingercontinues to write data until standby time
1919 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001920 * Avoid this by routing audio to speaker until standby.
1921 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301922 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1923 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001925 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1926 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 }
1928
1929 /*
1930 * select_devices() call below switches all the usecases on the same
1931 * backend to the new device. Refer to check_usecases_codec_backend() in
1932 * the select_devices(). But how do we undo this?
1933 *
1934 * For example, music playback is active on headset (deep-buffer usecase)
1935 * and if we go to ringtones and select a ringtone, low-latency usecase
1936 * will be started on headset+speaker. As we can't enable headset+speaker
1937 * and headset devices at the same time, select_devices() switches the music
1938 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1939 * So when the ringtone playback is completed, how do we undo the same?
1940 *
1941 * We are relying on the out_set_parameters() call on deep-buffer output,
1942 * once the ringtone playback is ended.
1943 * NOTE: We should not check if the current devices are same as new devices.
1944 * Because select_devices() must be called to switch back the music
1945 * playback to headset.
1946 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001947 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 out->devices = val;
1949
1950 if (!out->standby)
1951 select_devices(adev, out->usecase);
1952
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001953 if (output_drives_call(adev, out)) {
1954 if(!voice_is_in_call(adev)) {
1955 if (adev->mode == AUDIO_MODE_IN_CALL) {
1956 adev->current_call_output = out;
1957 ret = voice_start_call(adev);
1958 }
1959 } else {
1960 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001961 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001962 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 }
1964 }
1965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001967 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001969
1970 if (out == adev->primary_output) {
1971 pthread_mutex_lock(&adev->lock);
1972 audio_extn_set_parameters(adev, parms);
1973 pthread_mutex_unlock(&adev->lock);
1974 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001975 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001976 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001977 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001978
1979 audio_extn_dts_create_state_notifier_node(out->usecase);
1980 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1981 popcount(out->channel_mask),
1982 out->playback_started);
1983
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001984 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001985 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301988error:
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 return ret;
1991}
1992
1993static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1994{
1995 struct stream_out *out = (struct stream_out *)stream;
1996 struct str_parms *query = str_parms_create_str(keys);
1997 char *str;
1998 char value[256];
1999 struct str_parms *reply = str_parms_create();
2000 size_t i, j;
2001 int ret;
2002 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002003
2004 if (!query || !reply) {
2005 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2006 return NULL;
2007 }
2008
Eric Laurent994a6932013-07-17 11:51:42 -07002009 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2011 if (ret >= 0) {
2012 value[0] = '\0';
2013 i = 0;
2014 while (out->supported_channel_masks[i] != 0) {
2015 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2016 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2017 if (!first) {
2018 strcat(value, "|");
2019 }
2020 strcat(value, out_channels_name_to_enum_table[j].name);
2021 first = false;
2022 break;
2023 }
2024 }
2025 i++;
2026 }
2027 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2028 str = str_parms_to_str(reply);
2029 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002030 voice_extn_out_get_parameters(out, query, reply);
2031 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002032 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002033 free(str);
2034 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002035 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002037
2038 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2039 if (ret >= 0) {
2040 value[0] = '\0';
2041 i = 0;
2042 first = true;
2043 while (out->supported_formats[i] != 0) {
2044 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2045 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2046 if (!first) {
2047 strcat(value, "|");
2048 }
2049 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2050 first = false;
2051 break;
2052 }
2053 }
2054 i++;
2055 }
2056 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2057 str = str_parms_to_str(reply);
2058 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 str_parms_destroy(query);
2060 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002061 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062 return str;
2063}
2064
2065static uint32_t out_get_latency(const struct audio_stream_out *stream)
2066{
2067 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002068 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069
Alexy Josephaa54c872014-12-03 02:46:47 -08002070 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002071 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002072 } else {
2073 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002075 }
2076
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302077 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002078 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079}
2080
2081static int out_set_volume(struct audio_stream_out *stream, float left,
2082 float right)
2083{
Eric Laurenta9024de2013-04-04 09:19:12 -07002084 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085 int volume[2];
2086
Eric Laurenta9024de2013-04-04 09:19:12 -07002087 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2088 /* only take left channel into account: the API is for stereo anyway */
2089 out->muted = (left == 0.0f);
2090 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002091 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002092 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2093 /*
2094 * Set mute or umute on HDMI passthrough stream.
2095 * Only take left channel into account.
2096 * Mute is 0 and unmute 1
2097 */
2098 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2099 } else {
2100 char mixer_ctl_name[128];
2101 struct audio_device *adev = out->dev;
2102 struct mixer_ctl *ctl;
2103 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002104 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002106 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2107 "Compress Playback %d Volume", pcm_device_id);
2108 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2109 if (!ctl) {
2110 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2111 __func__, mixer_ctl_name);
2112 return -EINVAL;
2113 }
2114 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2115 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2116 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2117 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002119 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 return -ENOSYS;
2122}
2123
2124static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2125 size_t bytes)
2126{
2127 struct stream_out *out = (struct stream_out *)stream;
2128 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302129 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002130 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302133
Naresh Tanniru80659832014-06-04 18:17:56 +05302134 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002135 // increase written size during SSR to avoid mismatch
2136 // with the written frames count in AF
2137 if (!is_offload_usecase(out->usecase))
2138 out->written += bytes / (out->config.channels * sizeof(short));
2139
Naresh Tanniru80659832014-06-04 18:17:56 +05302140 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302141 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302142 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302143 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002144 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302145 //during SSR for compress usecase we should return error to flinger
2146 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2147 pthread_mutex_unlock(&out->lock);
2148 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302149 }
2150 }
2151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002153 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002154 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002155 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2156 ret = voice_extn_compress_voip_start_output_stream(out);
2157 else
2158 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002159 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002162 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 goto exit;
2164 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002165 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2166 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002169 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002170 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002171 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002172 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002173 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2174 out->send_new_metadata = 0;
2175 }
2176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302178 if (ret < 0)
2179 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002180 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002181 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302182 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302184 } else if (-ENETRESET == ret) {
2185 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2186 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2187 pthread_mutex_unlock(&out->lock);
2188 out_standby(&out->stream.common);
2189 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302191 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002192 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002193 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 out->playback_started = 1;
2195 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002196
2197 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2198 popcount(out->channel_mask),
2199 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 }
2201 pthread_mutex_unlock(&out->lock);
2202 return ret;
2203 } else {
2204 if (out->pcm) {
2205 if (out->muted)
2206 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002209
2210 if (adev->adm_request_focus)
2211 adev->adm_request_focus(adev->adm_data, out->handle);
2212
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002213 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2214 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2215 else
2216 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002217
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302218 if (ret < 0)
2219 ret = -errno;
2220 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002221 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002222
2223 if (adev->adm_abandon_focus)
2224 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 }
2227
2228exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302229 /* ToDo: There may be a corner case when SSR happens back to back during
2230 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302231 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302232 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302233 }
2234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 pthread_mutex_unlock(&out->lock);
2236
2237 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002238 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002239 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302240 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302241 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302242 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302243 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302244 out->standby = true;
2245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002247 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302248 out_get_sample_rate(&out->stream.common));
2249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 }
2251 return bytes;
2252}
2253
2254static int out_get_render_position(const struct audio_stream_out *stream,
2255 uint32_t *dsp_frames)
2256{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302258 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002259
2260 if (dsp_frames == NULL)
2261 return -EINVAL;
2262
2263 *dsp_frames = 0;
2264 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002265 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 pthread_mutex_lock(&out->lock);
2267 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302268 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302270 if (ret < 0)
2271 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 ALOGVV("%s rendered frames %d sample_rate %d",
2273 __func__, *dsp_frames, out->sample_rate);
2274 }
2275 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302276 if (-ENETRESET == ret) {
2277 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2278 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2279 return -EINVAL;
2280 } else if(ret < 0) {
2281 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2282 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302283 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2284 /*
2285 * Handle corner case where compress session is closed during SSR
2286 * and timestamp is queried
2287 */
2288 ALOGE(" ERROR: sound card not active, return error");
2289 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302290 } else {
2291 return 0;
2292 }
Zhou Song32a556e2015-05-05 10:46:56 +08002293 } else if (audio_is_linear_pcm(out->format)) {
2294 *dsp_frames = out->written;
2295 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 } else
2297 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298}
2299
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002300static int out_add_audio_effect(const struct audio_stream *stream __unused,
2301 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302{
2303 return 0;
2304}
2305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002306static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2307 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308{
2309 return 0;
2310}
2311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002312static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2313 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314{
2315 return -EINVAL;
2316}
2317
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002318static int out_get_presentation_position(const struct audio_stream_out *stream,
2319 uint64_t *frames, struct timespec *timestamp)
2320{
2321 struct stream_out *out = (struct stream_out *)stream;
2322 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002323 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002324
2325 pthread_mutex_lock(&out->lock);
2326
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002327 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002328 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302329 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002330 &out->sample_rate);
2331 ALOGVV("%s rendered frames %ld sample_rate %d",
2332 __func__, dsp_frames, out->sample_rate);
2333 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302334 if (ret < 0)
2335 ret = -errno;
2336 if (-ENETRESET == ret) {
2337 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2338 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2339 ret = -EINVAL;
2340 } else
2341 ret = 0;
2342
Eric Laurent949a0892013-09-20 09:20:13 -07002343 /* this is the best we can do */
2344 clock_gettime(CLOCK_MONOTONIC, timestamp);
2345 }
2346 } else {
2347 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002348 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002349 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2350 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002351 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002352 // This adjustment accounts for buffering after app processor.
2353 // It is based on estimated DSP latency per use case, rather than exact.
2354 signed_frames -=
2355 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2356
Eric Laurent949a0892013-09-20 09:20:13 -07002357 // It would be unusual for this value to be negative, but check just in case ...
2358 if (signed_frames >= 0) {
2359 *frames = signed_frames;
2360 ret = 0;
2361 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002362 }
2363 }
2364 }
2365
2366 pthread_mutex_unlock(&out->lock);
2367
2368 return ret;
2369}
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371static int out_set_callback(struct audio_stream_out *stream,
2372 stream_callback_t callback, void *cookie)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375
2376 ALOGV("%s", __func__);
2377 pthread_mutex_lock(&out->lock);
2378 out->offload_callback = callback;
2379 out->offload_cookie = cookie;
2380 pthread_mutex_unlock(&out->lock);
2381 return 0;
2382}
2383
2384static int out_pause(struct audio_stream_out* stream)
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387 int status = -ENOSYS;
2388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002389 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002390 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 pthread_mutex_lock(&out->lock);
2392 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302393 struct audio_device *adev = out->dev;
2394 int snd_scard_state = get_snd_card_state(adev);
2395
2396 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2397 status = compress_pause(out->compr);
2398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002400
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302401 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402 audio_extn_dts_notify_playback_state(out->usecase, 0,
2403 out->sample_rate, popcount(out->channel_mask),
2404 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 }
2406 pthread_mutex_unlock(&out->lock);
2407 }
2408 return status;
2409}
2410
2411static int out_resume(struct audio_stream_out* stream)
2412{
2413 struct stream_out *out = (struct stream_out *)stream;
2414 int status = -ENOSYS;
2415 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002416 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002417 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418 status = 0;
2419 pthread_mutex_lock(&out->lock);
2420 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302421 struct audio_device *adev = out->dev;
2422 int snd_scard_state = get_snd_card_state(adev);
2423
2424 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2425 status = compress_resume(out->compr);
2426
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002428
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302429 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002430 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2431 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 }
2433 pthread_mutex_unlock(&out->lock);
2434 }
2435 return status;
2436}
2437
2438static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2439{
2440 struct stream_out *out = (struct stream_out *)stream;
2441 int status = -ENOSYS;
2442 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002443 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444 pthread_mutex_lock(&out->lock);
2445 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2446 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2447 else
2448 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2449 pthread_mutex_unlock(&out->lock);
2450 }
2451 return status;
2452}
2453
2454static int out_flush(struct audio_stream_out* stream)
2455{
2456 struct stream_out *out = (struct stream_out *)stream;
2457 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002458 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002459 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002460 pthread_mutex_lock(&out->lock);
2461 stop_compressed_output_l(out);
2462 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002463 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 return 0;
2465 }
2466 return -ENOSYS;
2467}
2468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469/** audio_stream_in implementation **/
2470static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2471{
2472 struct stream_in *in = (struct stream_in *)stream;
2473
2474 return in->config.rate;
2475}
2476
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002477static int in_set_sample_rate(struct audio_stream *stream __unused,
2478 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479{
2480 return -ENOSYS;
2481}
2482
2483static size_t in_get_buffer_size(const struct audio_stream *stream)
2484{
2485 struct stream_in *in = (struct stream_in *)stream;
2486
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002487 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2488 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002489 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2490 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002491
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002492 return in->config.period_size *
2493 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494}
2495
2496static uint32_t in_get_channels(const struct audio_stream *stream)
2497{
2498 struct stream_in *in = (struct stream_in *)stream;
2499
2500 return in->channel_mask;
2501}
2502
2503static audio_format_t in_get_format(const struct audio_stream *stream)
2504{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505 struct stream_in *in = (struct stream_in *)stream;
2506
2507 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508}
2509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002510static int in_set_format(struct audio_stream *stream __unused,
2511 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512{
2513 return -ENOSYS;
2514}
2515
2516static int in_standby(struct audio_stream *stream)
2517{
2518 struct stream_in *in = (struct stream_in *)stream;
2519 struct audio_device *adev = in->dev;
2520 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302521 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2522 stream, in->usecase, use_case_table[in->usecase]);
2523
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002524 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2525 /* Ignore standby in case of voip call because the voip input
2526 * stream is closed in adev_close_input_stream()
2527 */
2528 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2529 return status;
2530 }
2531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002533 if (!in->standby && in->is_st_session) {
2534 ALOGD("%s: sound trigger pcm stop lab", __func__);
2535 audio_extn_sound_trigger_stop_lab(in);
2536 in->standby = 1;
2537 }
2538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002540 if (adev->adm_deregister_stream)
2541 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2542
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002543 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 if (in->pcm) {
2546 pcm_close(in->pcm);
2547 in->pcm = NULL;
2548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002550 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 }
2552 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002553 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 return status;
2555}
2556
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002557static int in_dump(const struct audio_stream *stream __unused,
2558 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559{
2560 return 0;
2561}
2562
2563static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2564{
2565 struct stream_in *in = (struct stream_in *)stream;
2566 struct audio_device *adev = in->dev;
2567 struct str_parms *parms;
2568 char *str;
2569 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002570 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302572 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 parms = str_parms_create_str(kvpairs);
2574
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302575 if (!parms)
2576 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002578 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002579
2580 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2581 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 val = atoi(value);
2583 /* no audio source uses val == 0 */
2584 if ((in->source != val) && (val != 0)) {
2585 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002586 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2587 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2588 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2589 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002590 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002591 err = voice_extn_compress_voip_open_input_stream(in);
2592 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002593 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002594 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002595 }
2596 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 }
2598 }
2599
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002600 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2601 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002603 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 in->device = val;
2605 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002606 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002607 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 }
2609 }
2610
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002611done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002613 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
2615 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302616error:
Eric Laurent994a6932013-07-17 11:51:42 -07002617 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 return ret;
2619}
2620
2621static char* in_get_parameters(const struct audio_stream *stream,
2622 const char *keys)
2623{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002624 struct stream_in *in = (struct stream_in *)stream;
2625 struct str_parms *query = str_parms_create_str(keys);
2626 char *str;
2627 char value[256];
2628 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002629
2630 if (!query || !reply) {
2631 ALOGE("in_get_parameters: failed to create query or reply");
2632 return NULL;
2633 }
2634
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002635 ALOGV("%s: enter: keys - %s", __func__, keys);
2636
2637 voice_extn_in_get_parameters(in, query, reply);
2638
2639 str = str_parms_to_str(reply);
2640 str_parms_destroy(query);
2641 str_parms_destroy(reply);
2642
2643 ALOGV("%s: exit: returns - %s", __func__, str);
2644 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645}
2646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002647static int in_set_gain(struct audio_stream_in *stream __unused,
2648 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649{
2650 return 0;
2651}
2652
2653static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2654 size_t bytes)
2655{
2656 struct stream_in *in = (struct stream_in *)stream;
2657 struct audio_device *adev = in->dev;
2658 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302659 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302662
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002663 if (in->is_st_session) {
2664 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2665 /* Read from sound trigger HAL */
2666 audio_extn_sound_trigger_read(in, buffer, bytes);
2667 pthread_mutex_unlock(&in->lock);
2668 return bytes;
2669 }
2670
2671 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2672 ALOGD(" %s: sound card is not active/SSR state", __func__);
2673 ret= -EIO;;
2674 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302675 }
2676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002678 pthread_mutex_lock(&adev->lock);
2679 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2680 ret = voice_extn_compress_voip_start_input_stream(in);
2681 else
2682 ret = start_input_stream(in);
2683 pthread_mutex_unlock(&adev->lock);
2684 if (ret != 0) {
2685 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 }
2687 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002688 if (adev->adm_register_input_stream)
2689 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002692 if (adev->adm_request_focus)
2693 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002696 if (audio_extn_ssr_get_enabled() &&
2697 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002698 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002699 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2700 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002701 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2702 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002703 else
2704 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302705 if (ret < 0)
2706 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 }
2708
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002709 if (adev->adm_abandon_focus)
2710 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 /*
2713 * Instead of writing zeroes here, we could trust the hardware
2714 * to always provide zeroes when muted.
2715 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302716 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2717 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 memset(buffer, 0, bytes);
2719
2720exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302721 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302722 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002723 if (-ENETRESET == ret)
2724 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 pthread_mutex_unlock(&in->lock);
2727
2728 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302729 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302730 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302731 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302732 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302733 in->standby = true;
2734 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302735 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002737 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002738 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302739 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 }
2741 return bytes;
2742}
2743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002744static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
2746 return 0;
2747}
2748
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002749static int add_remove_audio_effect(const struct audio_stream *stream,
2750 effect_handle_t effect,
2751 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002753 struct stream_in *in = (struct stream_in *)stream;
2754 int status = 0;
2755 effect_descriptor_t desc;
2756
2757 status = (*effect)->get_descriptor(effect, &desc);
2758 if (status != 0)
2759 return status;
2760
2761 pthread_mutex_lock(&in->lock);
2762 pthread_mutex_lock(&in->dev->lock);
2763 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2764 in->enable_aec != enable &&
2765 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2766 in->enable_aec = enable;
2767 if (!in->standby)
2768 select_devices(in->dev, in->usecase);
2769 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002770 if (in->enable_ns != enable &&
2771 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2772 in->enable_ns = enable;
2773 if (!in->standby)
2774 select_devices(in->dev, in->usecase);
2775 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002776 pthread_mutex_unlock(&in->dev->lock);
2777 pthread_mutex_unlock(&in->lock);
2778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 return 0;
2780}
2781
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002782static int in_add_audio_effect(const struct audio_stream *stream,
2783 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784{
Eric Laurent994a6932013-07-17 11:51:42 -07002785 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002786 return add_remove_audio_effect(stream, effect, true);
2787}
2788
2789static int in_remove_audio_effect(const struct audio_stream *stream,
2790 effect_handle_t effect)
2791{
Eric Laurent994a6932013-07-17 11:51:42 -07002792 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002793 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794}
2795
2796static int adev_open_output_stream(struct audio_hw_device *dev,
2797 audio_io_handle_t handle,
2798 audio_devices_t devices,
2799 audio_output_flags_t flags,
2800 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002801 struct audio_stream_out **stream_out,
2802 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803{
2804 struct audio_device *adev = (struct audio_device *)dev;
2805 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002806 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002807 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302810
2811 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2812 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2813 ALOGE(" sound card is not active rejecting compress output open request");
2814 return -EINVAL;
2815 }
2816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2818
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302819 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2820 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2821 devices, flags, &out->stream);
2822
2823
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002824 if (!out) {
2825 return -ENOMEM;
2826 }
2827
Haynes Mathew George204045b2015-02-25 20:32:03 -08002828 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2829 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 if (devices == AUDIO_DEVICE_NONE)
2832 devices = AUDIO_DEVICE_OUT_SPEAKER;
2833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 out->flags = flags;
2835 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002836 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002837 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 out->sample_rate = config->sample_rate;
2839 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2840 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002841 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002842 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002843 out->non_blocking = 0;
2844 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845
2846 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002847 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2848 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002849 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2850 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2851
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002852 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002853 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2854 ret = read_hdmi_channel_masks(out);
2855
2856 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2857 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002858 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002859 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002860 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002861
2862 if (config->sample_rate == 0)
2863 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2864 if (config->channel_mask == 0)
2865 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2866
2867 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2870 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002872 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002874 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2875 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002876 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 ret = voice_extn_compress_voip_open_output_stream(out);
2878 if (ret != 0) {
2879 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2880 __func__, ret);
2881 goto error_open;
2882 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2884 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2885 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2886 ALOGE("%s: Unsupported Offload information", __func__);
2887 ret = -EINVAL;
2888 goto error_open;
2889 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002890
2891 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2892 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2893 ALOGV("read and update_pass through formats");
2894 ret = audio_extn_dolby_update_passt_formats(adev, out);
2895 if(ret != 0) {
2896 goto error_open;
2897 }
2898 if(config->offload_info.format == 0)
2899 config->offload_info.format = out->supported_formats[0];
2900 }
2901
Mingming Yin90310102013-11-13 16:57:00 -08002902 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002903 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 ALOGE("%s: Unsupported audio format", __func__);
2905 ret = -EINVAL;
2906 goto error_open;
2907 }
2908
2909 out->compr_config.codec = (struct snd_codec *)
2910 calloc(1, sizeof(struct snd_codec));
2911
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002912 if (!out->compr_config.codec) {
2913 ret = -ENOMEM;
2914 goto error_open;
2915 }
2916
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002917 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 if (config->offload_info.channel_mask)
2919 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002920 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002922 config->offload_info.channel_mask = config->channel_mask;
2923 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002924 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 out->sample_rate = config->offload_info.sample_rate;
2926
2927 out->stream.set_callback = out_set_callback;
2928 out->stream.pause = out_pause;
2929 out->stream.resume = out_resume;
2930 out->stream.drain = out_drain;
2931 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002932 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002934 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002935 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002936 audio_extn_dolby_get_snd_codec_id(adev, out,
2937 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002938 else
2939 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat2ec445f2015-07-23 18:02:31 +05302941 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002942 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002943 platform_get_pcm_offload_buffer_size(&config->offload_info);
2944 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2945 out->compr_config.fragment_size =
2946 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002947 } else {
2948 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002949 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002950 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2952 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002953 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 out->compr_config.codec->bit_rate =
2955 config->offload_info.bit_rate;
2956 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002957 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302959 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002960 /*TODO: Do we need to change it for passthrough */
2961 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962
Mingming Yin3ee55c62014-08-04 14:23:35 -07002963 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2964 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002965 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2966 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002967 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002968 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2969
Mingming Yin3ee55c62014-08-04 14:23:35 -07002970 if (out->bit_width == 24) {
2971 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2972 }
2973
Amit Shekhar6f461b12014-08-01 14:52:58 -07002974 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302975 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002976
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2978 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002979
Mingming Yin497419f2015-07-01 16:57:32 -07002980 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002981 //this flag is set from framework only if its for PCM formats
2982 //no need to check for PCM format again
2983 out->non_blocking = 0;
2984 out->use_small_bufs = true;
2985 ALOGI("Keep write blocking for small buff: non_blockling %d",
2986 out->non_blocking);
2987 }
2988
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002989 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002990 out->offload_state = OFFLOAD_STATE_IDLE;
2991 out->playback_started = 0;
2992
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002993 audio_extn_dts_create_state_notifier_node(out->usecase);
2994
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002995 create_offload_callback_thread(out);
2996 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2997 __func__, config->offload_info.version,
2998 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002999 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003000 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003001 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3002 ret = voice_check_and_set_incall_music_usecase(adev, out);
3003 if (ret != 0) {
3004 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3005 __func__, ret);
3006 goto error_open;
3007 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003008 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3009 if (config->sample_rate == 0)
3010 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3011 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3012 config->sample_rate != 8000) {
3013 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3014 ret = -EINVAL;
3015 goto error_open;
3016 }
3017 out->sample_rate = config->sample_rate;
3018 out->config.rate = config->sample_rate;
3019 if (config->format == AUDIO_FORMAT_DEFAULT)
3020 config->format = AUDIO_FORMAT_PCM_16_BIT;
3021 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3022 config->format = AUDIO_FORMAT_PCM_16_BIT;
3023 ret = -EINVAL;
3024 goto error_open;
3025 }
3026 out->format = config->format;
3027 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3028 out->config = pcm_config_afe_proxy_playback;
3029 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003030 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003031 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3033 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003035 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3036 format = AUDIO_FORMAT_PCM_16_BIT;
3037 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3038 out->config = pcm_config_deep_buffer;
3039 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003040 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003041 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003042 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003043 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003044 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003045 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046 }
3047
Amit Shekhar1d896042014-10-03 13:16:09 -07003048 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3049 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003050 /* TODO remove this hardcoding and check why width is zero*/
3051 if (out->bit_width == 0)
3052 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003053 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3054 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003055 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003056 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003057 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3058 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3059 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003060 if(adev->primary_output == NULL)
3061 adev->primary_output = out;
3062 else {
3063 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064 ret = -EEXIST;
3065 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003066 }
3067 }
3068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 /* Check if this usecase is already existing */
3070 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003071 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3072 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003075 ret = -EEXIST;
3076 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 }
3078 pthread_mutex_unlock(&adev->lock);
3079
3080 out->stream.common.get_sample_rate = out_get_sample_rate;
3081 out->stream.common.set_sample_rate = out_set_sample_rate;
3082 out->stream.common.get_buffer_size = out_get_buffer_size;
3083 out->stream.common.get_channels = out_get_channels;
3084 out->stream.common.get_format = out_get_format;
3085 out->stream.common.set_format = out_set_format;
3086 out->stream.common.standby = out_standby;
3087 out->stream.common.dump = out_dump;
3088 out->stream.common.set_parameters = out_set_parameters;
3089 out->stream.common.get_parameters = out_get_parameters;
3090 out->stream.common.add_audio_effect = out_add_audio_effect;
3091 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3092 out->stream.get_latency = out_get_latency;
3093 out->stream.set_volume = out_set_volume;
3094 out->stream.write = out_write;
3095 out->stream.get_render_position = out_get_render_position;
3096 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003097 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003100 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003101 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102
3103 config->format = out->stream.common.get_format(&out->stream.common);
3104 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3105 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3106
3107 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303108 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3109 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003110
3111 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3112 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3113 popcount(out->channel_mask), out->playback_started);
3114
Eric Laurent994a6932013-07-17 11:51:42 -07003115 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003117
3118error_open:
3119 free(out);
3120 *stream_out = NULL;
3121 ALOGD("%s: exit: ret %d", __func__, ret);
3122 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123}
3124
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003125static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 struct audio_stream_out *stream)
3127{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 struct stream_out *out = (struct stream_out *)stream;
3129 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003130 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003131
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303132 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3133
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003134 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303135 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003136 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303137 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003138 if(ret != 0)
3139 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3140 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003141 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003142 out_standby(&stream->common);
3143
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003144 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003145 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003147 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 if (out->compr_config.codec != NULL)
3149 free(out->compr_config.codec);
3150 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003151
3152 if (adev->voice_tx_output == out)
3153 adev->voice_tx_output = NULL;
3154
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003155 pthread_cond_destroy(&out->cond);
3156 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003158 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159}
3160
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003161static void close_compress_sessions(struct audio_device *adev)
3162{
Mingming Yin7b762e72015-03-04 13:47:32 -08003163 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303164 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003165 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003166 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303167
3168 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003169 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303170 if (is_offload_usecase(usecase->id)) {
3171 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003172 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3173 out = usecase->stream.out;
3174 pthread_mutex_unlock(&adev->lock);
3175 out_standby(&out->stream.common);
3176 pthread_mutex_lock(&adev->lock);
3177 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303178 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003179 }
3180 pthread_mutex_unlock(&adev->lock);
3181}
3182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3184{
3185 struct audio_device *adev = (struct audio_device *)dev;
3186 struct str_parms *parms;
3187 char *str;
3188 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003189 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003190 int ret;
3191 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003193 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303196 if (!parms)
3197 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3199 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303200 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303201 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303202 struct listnode *node;
3203 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303204 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303205 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003206 //close compress sessions on OFFLINE status
3207 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303208 } else if (strstr(snd_card_status, "ONLINE")) {
3209 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303210 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003211 //send dts hpx license if enabled
3212 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303213 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303214 }
3215
3216 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003217 status = voice_set_parameters(adev, parms);
3218 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003219 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003221 status = platform_set_parameters(adev->platform, parms);
3222 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003223 goto done;
3224
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003225 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3226 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003227 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3229 adev->bluetooth_nrec = true;
3230 else
3231 adev->bluetooth_nrec = false;
3232 }
3233
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003234 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3235 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3237 adev->screen_off = false;
3238 else
3239 adev->screen_off = true;
3240 }
3241
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003242 ret = str_parms_get_int(parms, "rotation", &val);
3243 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003244 bool reverse_speakers = false;
3245 switch(val) {
3246 // FIXME: note that the code below assumes that the speakers are in the correct placement
3247 // relative to the user when the device is rotated 90deg from its default rotation. This
3248 // assumption is device-specific, not platform-specific like this code.
3249 case 270:
3250 reverse_speakers = true;
3251 break;
3252 case 0:
3253 case 90:
3254 case 180:
3255 break;
3256 default:
3257 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003258 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003259 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003260 if (status == 0) {
3261 if (adev->speaker_lr_swap != reverse_speakers) {
3262 adev->speaker_lr_swap = reverse_speakers;
3263 // only update the selected device if there is active pcm playback
3264 struct audio_usecase *usecase;
3265 struct listnode *node;
3266 list_for_each(node, &adev->usecase_list) {
3267 usecase = node_to_item(node, struct audio_usecase, list);
3268 if (usecase->type == PCM_PLAYBACK) {
3269 select_devices(adev, usecase->id);
3270 break;
3271 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003272 }
3273 }
3274 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003275 }
3276
Mingming Yin514a8bc2014-07-29 15:22:21 -07003277 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3278 if (ret >= 0) {
3279 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3280 adev->bt_wb_speech_enabled = true;
3281 else
3282 adev->bt_wb_speech_enabled = false;
3283 }
3284
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003285 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3286 if (ret >= 0) {
3287 val = atoi(value);
3288 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3289 ALOGV("cache new edid");
3290 platform_cache_edid(adev->platform);
3291 }
3292 }
3293
3294 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3295 if (ret >= 0) {
3296 val = atoi(value);
3297 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3298 ALOGV("invalidate cached edid");
3299 platform_invalidate_edid(adev->platform);
3300 }
3301 }
3302
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003303 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003304
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003305done:
3306 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003307 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303308error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003309 ALOGV("%s: exit with code(%d)", __func__, status);
3310 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
3313static char* adev_get_parameters(const struct audio_hw_device *dev,
3314 const char *keys)
3315{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003316 struct audio_device *adev = (struct audio_device *)dev;
3317 struct str_parms *reply = str_parms_create();
3318 struct str_parms *query = str_parms_create_str(keys);
3319 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303320 char value[256] = {0};
3321 int ret = 0;
3322
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003323 if (!query || !reply) {
3324 ALOGE("adev_get_parameters: failed to create query or reply");
3325 return NULL;
3326 }
3327
Naresh Tannirud7205b62014-06-20 02:54:48 +05303328 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3329 sizeof(value));
3330 if (ret >=0) {
3331 int val = 1;
3332 pthread_mutex_lock(&adev->snd_card_status.lock);
3333 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3334 val = 0;
3335 pthread_mutex_unlock(&adev->snd_card_status.lock);
3336 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3337 goto exit;
3338 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003339
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003340 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003341 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003342 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003343 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303344 pthread_mutex_unlock(&adev->lock);
3345
Naresh Tannirud7205b62014-06-20 02:54:48 +05303346exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003347 str = str_parms_to_str(reply);
3348 str_parms_destroy(query);
3349 str_parms_destroy(reply);
3350
3351 ALOGV("%s: exit: returns - %s", __func__, str);
3352 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353}
3354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003355static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356{
3357 return 0;
3358}
3359
3360static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3361{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003362 int ret;
3363 struct audio_device *adev = (struct audio_device *)dev;
3364 pthread_mutex_lock(&adev->lock);
3365 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003366 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003367 pthread_mutex_unlock(&adev->lock);
3368 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369}
3370
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003371static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3372 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373{
3374 return -ENOSYS;
3375}
3376
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003377static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3378 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379{
3380 return -ENOSYS;
3381}
3382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003383static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3384 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
3386 return -ENOSYS;
3387}
3388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3390 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 return -ENOSYS;
3393}
3394
3395static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3396{
3397 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 pthread_mutex_lock(&adev->lock);
3400 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003401 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003403 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3404 voice_is_in_call(adev)) {
3405 voice_stop_call(adev);
3406 adev->current_call_output = NULL;
3407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 }
3409 pthread_mutex_unlock(&adev->lock);
3410 return 0;
3411}
3412
3413static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3414{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003415 int ret;
3416
3417 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003418 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003419 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3420 pthread_mutex_unlock(&adev->lock);
3421
3422 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423}
3424
3425static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3426{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003427 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 return 0;
3429}
3430
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003431static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 const struct audio_config *config)
3433{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003434 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003436 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3437 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438}
3439
3440static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003441 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 audio_devices_t devices,
3443 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003444 struct audio_stream_in **stream_in,
3445 audio_input_flags_t flags __unused,
3446 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003447 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448{
3449 struct audio_device *adev = (struct audio_device *)dev;
3450 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003451 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003452 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003453 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 *stream_in = NULL;
3456 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3457 return -EINVAL;
3458
3459 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003460
3461 if (!in) {
3462 ALOGE("failed to allocate input stream");
3463 return -ENOMEM;
3464 }
3465
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303466 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003467 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3468 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003470 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 in->stream.common.get_sample_rate = in_get_sample_rate;
3473 in->stream.common.set_sample_rate = in_set_sample_rate;
3474 in->stream.common.get_buffer_size = in_get_buffer_size;
3475 in->stream.common.get_channels = in_get_channels;
3476 in->stream.common.get_format = in_get_format;
3477 in->stream.common.set_format = in_set_format;
3478 in->stream.common.standby = in_standby;
3479 in->stream.common.dump = in_dump;
3480 in->stream.common.set_parameters = in_set_parameters;
3481 in->stream.common.get_parameters = in_get_parameters;
3482 in->stream.common.add_audio_effect = in_add_audio_effect;
3483 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3484 in->stream.set_gain = in_set_gain;
3485 in->stream.read = in_read;
3486 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3487
3488 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003489 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 in->standby = 1;
3492 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003493 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003494 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495
3496 /* Update config params with the requested sample rate and channels */
3497 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003498 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3499 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3500 is_low_latency = true;
3501#if LOW_LATENCY_CAPTURE_USE_CASE
3502 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3503#endif
3504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003507 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003509 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303510 if (adev->mode != AUDIO_MODE_IN_CALL) {
3511 ret = -EINVAL;
3512 goto err_open;
3513 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003514 if (config->sample_rate == 0)
3515 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3516 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3517 config->sample_rate != 8000) {
3518 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3519 ret = -EINVAL;
3520 goto err_open;
3521 }
3522 if (config->format == AUDIO_FORMAT_DEFAULT)
3523 config->format = AUDIO_FORMAT_PCM_16_BIT;
3524 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3525 config->format = AUDIO_FORMAT_PCM_16_BIT;
3526 ret = -EINVAL;
3527 goto err_open;
3528 }
3529
3530 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3531 in->config = pcm_config_afe_proxy_record;
3532 in->config.channels = channel_count;
3533 in->config.rate = config->sample_rate;
3534 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003535 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003537 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3538 ret = -EINVAL;
3539 goto err_open;
3540 }
3541 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003542 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003543 }
Mingming Yine62d7842013-10-25 16:26:03 -07003544 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003545 audio_extn_compr_cap_format_supported(config->format) &&
3546 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003547 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003548 } else {
3549 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003550 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003551 buffer_size = get_input_buffer_size(config->sample_rate,
3552 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003553 channel_count,
3554 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003555 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003556 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3557 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3558 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3559 (in->config.rate == 8000 || in->config.rate == 16000) &&
3560 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3561 voice_extn_compress_voip_open_input_stream(in);
3562 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003565 /* This stream could be for sound trigger lab,
3566 get sound trigger pcm if present */
3567 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303568 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003571 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003572 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573
3574err_open:
3575 free(in);
3576 *stream_in = NULL;
3577 return ret;
3578}
3579
3580static void adev_close_input_stream(struct audio_hw_device *dev,
3581 struct audio_stream_in *stream)
3582{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003583 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003584 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003585 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303586
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303587 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003588
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303589 /* Disable echo reference while closing input stream */
3590 platform_set_echo_reference(adev->platform, false);
3591
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303593 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003594 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303595 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003596 if (ret != 0)
3597 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3598 __func__, ret);
3599 } else
3600 in_standby(&stream->common);
3601
Mingming Yin7b762e72015-03-04 13:47:32 -08003602 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003603 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003604 audio_extn_ssr_deinit();
3605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606
Mingming Yine62d7842013-10-25 16:26:03 -07003607 if(audio_extn_compr_cap_enabled() &&
3608 audio_extn_compr_cap_format_supported(in->config.format))
3609 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003610
3611 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 return;
3613}
3614
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003615static int adev_dump(const audio_hw_device_t *device __unused,
3616 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 return 0;
3619}
3620
3621static int adev_close(hw_device_t *device)
3622{
3623 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003624
3625 if (!adev)
3626 return 0;
3627
3628 pthread_mutex_lock(&adev_init_lock);
3629
3630 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003631 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003632 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003633 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003634 audio_route_free(adev->audio_route);
3635 free(adev->snd_dev_ref_cnt);
3636 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003637 if (adev->adm_deinit)
3638 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003639 free(device);
3640 adev = NULL;
3641 }
3642 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 return 0;
3645}
3646
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003647/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3648 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3649 * just that it _might_ work.
3650 */
3651static int period_size_is_plausible_for_low_latency(int period_size)
3652{
3653 switch (period_size) {
3654 case 160:
3655 case 240:
3656 case 320:
3657 case 480:
3658 return 1;
3659 default:
3660 return 0;
3661 }
3662}
3663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664static int adev_open(const hw_module_t *module, const char *name,
3665 hw_device_t **device)
3666{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003667 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003669 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3671
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003672 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003673 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003674 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003675 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003676 ALOGD("%s: returning existing instance of adev", __func__);
3677 ALOGD("%s: exit", __func__);
3678 pthread_mutex_unlock(&adev_init_lock);
3679 return 0;
3680 }
3681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 adev = calloc(1, sizeof(struct audio_device));
3683
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003684 if (!adev) {
3685 pthread_mutex_unlock(&adev_init_lock);
3686 return -ENOMEM;
3687 }
3688
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003689 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3692 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3693 adev->device.common.module = (struct hw_module_t *)module;
3694 adev->device.common.close = adev_close;
3695
3696 adev->device.init_check = adev_init_check;
3697 adev->device.set_voice_volume = adev_set_voice_volume;
3698 adev->device.set_master_volume = adev_set_master_volume;
3699 adev->device.get_master_volume = adev_get_master_volume;
3700 adev->device.set_master_mute = adev_set_master_mute;
3701 adev->device.get_master_mute = adev_get_master_mute;
3702 adev->device.set_mode = adev_set_mode;
3703 adev->device.set_mic_mute = adev_set_mic_mute;
3704 adev->device.get_mic_mute = adev_get_mic_mute;
3705 adev->device.set_parameters = adev_set_parameters;
3706 adev->device.get_parameters = adev_get_parameters;
3707 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3708 adev->device.open_output_stream = adev_open_output_stream;
3709 adev->device.close_output_stream = adev_close_output_stream;
3710 adev->device.open_input_stream = adev_open_input_stream;
3711 adev->device.close_input_stream = adev_close_input_stream;
3712 adev->device.dump = adev_dump;
3713
3714 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003716 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003717 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003720 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003721 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003722 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003723 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003724 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003725 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003726 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303727
3728 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3729 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003731 adev->platform = platform_init(adev);
3732 if (!adev->platform) {
3733 free(adev->snd_dev_ref_cnt);
3734 free(adev);
3735 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3736 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003737 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003738 return -EINVAL;
3739 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003740
Naresh Tanniru4c630392014-05-12 01:05:52 +05303741 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3742
Eric Laurentc4aef752013-09-12 17:45:53 -07003743 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3744 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3745 if (adev->visualizer_lib == NULL) {
3746 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3747 } else {
3748 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3749 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003750 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003751 "visualizer_hal_start_output");
3752 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003753 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003754 "visualizer_hal_stop_output");
3755 }
3756 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003757 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003758 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003759
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003760 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3761 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3762 if (adev->offload_effects_lib == NULL) {
3763 ALOGE("%s: DLOPEN failed for %s", __func__,
3764 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3765 } else {
3766 ALOGV("%s: DLOPEN successful for %s", __func__,
3767 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3768 adev->offload_effects_start_output =
3769 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3770 "offload_effects_bundle_hal_start_output");
3771 adev->offload_effects_stop_output =
3772 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3773 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003774 adev->offload_effects_set_hpx_state =
3775 (int (*)(bool))dlsym(adev->offload_effects_lib,
3776 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003777 }
3778 }
3779
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003780 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3781 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3782 if (adev->adm_lib == NULL) {
3783 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3784 } else {
3785 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3786 adev->adm_init = (adm_init_t)
3787 dlsym(adev->adm_lib, "adm_init");
3788 adev->adm_deinit = (adm_deinit_t)
3789 dlsym(adev->adm_lib, "adm_deinit");
3790 adev->adm_register_input_stream = (adm_register_input_stream_t)
3791 dlsym(adev->adm_lib, "adm_register_input_stream");
3792 adev->adm_register_output_stream = (adm_register_output_stream_t)
3793 dlsym(adev->adm_lib, "adm_register_output_stream");
3794 adev->adm_deregister_stream = (adm_deregister_stream_t)
3795 dlsym(adev->adm_lib, "adm_deregister_stream");
3796 adev->adm_request_focus = (adm_request_focus_t)
3797 dlsym(adev->adm_lib, "adm_request_focus");
3798 adev->adm_abandon_focus = (adm_abandon_focus_t)
3799 dlsym(adev->adm_lib, "adm_abandon_focus");
3800 }
3801 }
3802
Mingming Yin514a8bc2014-07-29 15:22:21 -07003803 adev->bt_wb_speech_enabled = false;
3804
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003805 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 *device = &adev->device.common;
3807
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003808 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3809 &adev->streams_output_cfg_list);
3810
Kiran Kandi910e1862013-10-29 13:29:42 -07003811 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003812
3813 char value[PROPERTY_VALUE_MAX];
3814 int trial;
3815 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3816 trial = atoi(value);
3817 if (period_size_is_plausible_for_low_latency(trial)) {
3818 pcm_config_low_latency.period_size = trial;
3819 pcm_config_low_latency.start_threshold = trial / 4;
3820 pcm_config_low_latency.avail_min = trial / 4;
3821 configured_low_latency_capture_period_size = trial;
3822 }
3823 }
3824 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3825 trial = atoi(value);
3826 if (period_size_is_plausible_for_low_latency(trial)) {
3827 configured_low_latency_capture_period_size = trial;
3828 }
3829 }
3830
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003831 pthread_mutex_unlock(&adev_init_lock);
3832
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003833 if (adev->adm_init)
3834 adev->adm_data = adev->adm_init();
3835
Eric Laurent994a6932013-07-17 11:51:42 -07003836 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 return 0;
3838}
3839
3840static struct hw_module_methods_t hal_module_methods = {
3841 .open = adev_open,
3842};
3843
3844struct audio_module HAL_MODULE_INFO_SYM = {
3845 .common = {
3846 .tag = HARDWARE_MODULE_TAG,
3847 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3848 .hal_api_version = HARDWARE_HAL_API_VERSION,
3849 .id = AUDIO_HARDWARE_MODULE_ID,
3850 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003851 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 .methods = &hal_module_methods,
3853 },
3854};