blob: 435c57d311ca96d05de36b470acd372e48f0ad95 [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 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530308 format == AUDIO_FORMAT_AAC_ADTS_LC ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
310 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800311 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700312 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800339 id = SND_AUDIOCODEC_PCM;
340 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700341 case AUDIO_FORMAT_FLAC:
342 id = SND_AUDIOCODEC_FLAC;
343 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530344 case AUDIO_FORMAT_ALAC:
345 id = SND_AUDIOCODEC_ALAC;
346 break;
347 case AUDIO_FORMAT_APE:
348 id = SND_AUDIOCODEC_APE;
349 break;
350 case AUDIO_FORMAT_VORBIS:
351 id = SND_AUDIOCODEC_VORBIS;
352 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800353 case AUDIO_FORMAT_WMA:
354 id = SND_AUDIOCODEC_WMA;
355 break;
356 case AUDIO_FORMAT_WMA_PRO:
357 id = SND_AUDIOCODEC_WMA_PRO;
358 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700359 default:
Mingming Yin90310102013-11-13 16:57:00 -0800360 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700361 }
362
363 return id;
364}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800365
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530366int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530367{
368 int snd_scard_state;
369
370 if (!adev)
371 return SND_CARD_STATE_OFFLINE;
372
373 pthread_mutex_lock(&adev->snd_card_status.lock);
374 snd_scard_state = adev->snd_card_status.state;
375 pthread_mutex_unlock(&adev->snd_card_status.lock);
376
377 return snd_scard_state;
378}
379
380static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
381{
382 if (!adev)
383 return -ENOSYS;
384
385 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700386 if (adev->snd_card_status.state != snd_scard_state) {
387 adev->snd_card_status.state = snd_scard_state;
388 platform_snd_card_update(adev->platform, snd_scard_state);
389 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530390 pthread_mutex_unlock(&adev->snd_card_status.lock);
391
392 return 0;
393}
394
Avinash Vaish71a8b972014-07-24 15:36:33 +0530395static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
396 struct audio_usecase *uc_info)
397{
398 struct listnode *node;
399 struct audio_usecase *usecase;
400
401 if (uc_info == NULL)
402 return -EINVAL;
403
404 /* Re-route all voice usecases on the shared backend other than the
405 specified usecase to new snd devices */
406 list_for_each(node, &adev->usecase_list) {
407 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800408 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530409 enable_audio_route(adev, usecase);
410 }
411 return 0;
412}
413
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700414int pcm_ioctl(struct pcm *pcm, int request, ...)
415{
416 va_list ap;
417 void * arg;
418 int pcm_fd = *(int*)pcm;
419
420 va_start(ap, request);
421 arg = va_arg(ap, void *);
422 va_end(ap);
423
424 return ioctl(pcm_fd, request, arg);
425}
426
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700427int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700428 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700430 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432
433 if (usecase == NULL)
434 return -EINVAL;
435
436 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
437
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700439 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800440 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800442
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800443#ifdef DS1_DOLBY_DAP_ENABLED
444 audio_extn_dolby_set_dmid(adev);
445 audio_extn_dolby_set_endpoint(adev);
446#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700447 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700448 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530449 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700450 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700451 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800452 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700453 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700454 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
455 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 ALOGV("%s: exit", __func__);
457 return 0;
458}
459
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700460int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700461 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700463 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700464 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800465
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530466 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800467 return -EINVAL;
468
469 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700470 if (usecase->type == PCM_CAPTURE)
471 snd_device = usecase->in_snd_device;
472 else
473 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800474 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700475 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700476 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
477 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700478 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530479 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480 ALOGV("%s: exit", __func__);
481 return 0;
482}
483
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700484int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700485 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700487 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
488
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800489 if (snd_device < SND_DEVICE_MIN ||
490 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800491 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800492 return -EINVAL;
493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700494
495 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700496
497 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
498 ALOGE("%s: Invalid sound device returned", __func__);
499 return -EINVAL;
500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700501 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700502 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700503 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700504 return 0;
505 }
506
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700507 if (audio_extn_spkr_prot_is_enabled())
508 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700509 /* start usb playback thread */
510 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
511 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
512 audio_extn_usb_start_playback(adev);
513
514 /* start usb capture thread */
515 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
516 audio_extn_usb_start_capture(adev);
517
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800518 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
519 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700520 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700521 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
522 adev->snd_dev_ref_cnt[snd_device]--;
523 return -EINVAL;
524 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200525 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800526 if (audio_extn_spkr_prot_start_processing(snd_device)) {
527 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200528 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800529 return -EINVAL;
530 }
531 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700532 ALOGV("%s: snd_device(%d: %s)", __func__,
533 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 return 0;
552}
553
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700554int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700555 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700557 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
558
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800559 if (snd_device < SND_DEVICE_MIN ||
560 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800561 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800562 return -EINVAL;
563 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
565 ALOGE("%s: device ref cnt is already 0", __func__);
566 return -EINVAL;
567 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700568
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700570
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700571 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
572 ALOGE("%s: Invalid sound device returned", __func__);
573 return -EINVAL;
574 }
575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700577 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800579 /* exit usb play back thread */
580 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
581 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
582 audio_extn_usb_stop_playback();
583
584 /* exit usb capture thread */
585 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700586 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800587
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800588 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
589 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700590 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700591 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300592 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700593 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300594 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700595
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200596 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700597 audio_extn_sound_trigger_update_device_status(snd_device,
598 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530599 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800600 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 return 0;
604}
605
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606static void check_usecases_codec_backend(struct audio_device *adev,
607 struct audio_usecase *uc_info,
608 snd_device_t snd_device)
609{
610 struct listnode *node;
611 struct audio_usecase *usecase;
612 bool switch_device[AUDIO_USECASE_MAX];
613 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800614 int backend_idx = DEFAULT_CODEC_BACKEND;
615 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616
617 /*
618 * This function is to make sure that all the usecases that are active on
619 * the hardware codec backend are always routed to any one device that is
620 * handled by the hardware codec.
621 * For example, if low-latency and deep-buffer usecases are currently active
622 * on speaker and out_set_parameters(headset) is received on low-latency
623 * output, then we have to make sure deep-buffer is also switched to headset,
624 * because of the limitation that both the devices cannot be enabled
625 * at the same time as they share the same backend.
626 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 /*
628 * This call is to check if we need to force routing for a particular stream
629 * If there is a backend configuration change for the device when a
630 * new stream starts, then ADM needs to be closed and re-opened with the new
631 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800632 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700633 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800634 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
635 snd_device);
636 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800638 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800639 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 for (i = 0; i < AUDIO_USECASE_MAX; i++)
641 switch_device[i] = false;
642
643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800645
646 if (usecase == uc_info)
647 continue;
648 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
649 ALOGV("%s: backend_idx: %d,"
650 "usecase_backend_idx: %d, curr device: %s, usecase device:"
651 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530652 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800654 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700655 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800656 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
657 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530658 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700660 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 switch_device[usecase->id] = true;
663 num_uc_to_switch++;
664 }
665 }
666
667 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700668 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530670 /* Make sure the previous devices to be disabled first and then enable the
671 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 list_for_each(node, &adev->usecase_list) {
673 usecase = node_to_item(node, struct audio_usecase, list);
674 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700675 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 }
677 }
678
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700679 list_for_each(node, &adev->usecase_list) {
680 usecase = node_to_item(node, struct audio_usecase, list);
681 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700682 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700683 }
684 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 /* Re-route all the usecases on the shared backend other than the
687 specified usecase to new snd devices */
688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530690 /* Update the out_snd_device only for the usecases that are enabled here */
691 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
692 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530693 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 }
695 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 }
697}
698
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700699static void check_and_route_capture_usecases(struct audio_device *adev,
700 struct audio_usecase *uc_info,
701 snd_device_t snd_device)
702{
703 struct listnode *node;
704 struct audio_usecase *usecase;
705 bool switch_device[AUDIO_USECASE_MAX];
706 int i, num_uc_to_switch = 0;
707
708 /*
709 * This function is to make sure that all the active capture usecases
710 * are always routed to the same input sound device.
711 * For example, if audio-record and voice-call usecases are currently
712 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
713 * is received for voice call then we have to make sure that audio-record
714 * usecase is also switched to earpiece i.e. voice-dmic-ef,
715 * because of the limitation that two devices cannot be enabled
716 * at the same time if they share the same backend.
717 */
718 for (i = 0; i < AUDIO_USECASE_MAX; i++)
719 switch_device[i] = false;
720
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800723 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700725 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700726 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
727 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700728 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
730 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700731 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 switch_device[usecase->id] = true;
734 num_uc_to_switch++;
735 }
736 }
737
738 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700739 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700740
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530741 /* Make sure the previous devices to be disabled first and then enable the
742 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 list_for_each(node, &adev->usecase_list) {
744 usecase = node_to_item(node, struct audio_usecase, list);
745 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700746 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800747 }
748 }
749
750 list_for_each(node, &adev->usecase_list) {
751 usecase = node_to_item(node, struct audio_usecase, list);
752 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700753 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 }
755 }
756
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757 /* Re-route all the usecases on the shared backend other than the
758 specified usecase to new snd devices */
759 list_for_each(node, &adev->usecase_list) {
760 usecase = node_to_item(node, struct audio_usecase, list);
761 /* Update the in_snd_device only before enabling the audio route */
762 if (switch_device[usecase->id] ) {
763 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800764 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530765 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 }
767 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700768 }
769}
770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700772static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700774 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700775 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776
777 switch (channels) {
778 /*
779 * Do not handle stereo output in Multi-channel cases
780 * Stereo case is handled in normal playback path
781 */
782 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700783 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 break;
790 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700791 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800798 break;
799 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700800 ALOGE("HDMI does not support multi channel playback");
801 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800802 break;
803 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700804 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805}
806
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800807audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
808 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700809{
810 struct audio_usecase *usecase;
811 struct listnode *node;
812
813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800815 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700816 ALOGV("%s: usecase id %d", __func__, usecase->id);
817 return usecase->id;
818 }
819 }
820 return USECASE_INVALID;
821}
822
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700823struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700824 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825{
826 struct audio_usecase *usecase;
827 struct listnode *node;
828
829 list_for_each(node, &adev->usecase_list) {
830 usecase = node_to_item(node, struct audio_usecase, list);
831 if (usecase->id == uc_id)
832 return usecase;
833 }
834 return NULL;
835}
836
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700837int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800839 snd_device_t out_snd_device = SND_DEVICE_NONE;
840 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 struct audio_usecase *usecase = NULL;
842 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800843 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800844 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800845 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800846 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 usecase = get_usecase_from_list(adev, uc_id);
850 if (usecase == NULL) {
851 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
852 return -EINVAL;
853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800855 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800856 (usecase->type == VOIP_CALL) ||
857 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700858 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800859 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700860 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 usecase->devices = usecase->stream.out->devices;
862 } else {
863 /*
864 * If the voice call is active, use the sound devices of voice call usecase
865 * so that it would not result any device switch. All the usecases will
866 * be switched to new device when select_devices() is called for voice call
867 * usecase. This is to avoid switching devices for voice call when
868 * check_usecases_codec_backend() is called below.
869 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700870 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700871 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800872 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700873 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
874 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 in_snd_device = vc_usecase->in_snd_device;
876 out_snd_device = vc_usecase->out_snd_device;
877 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800878 } else if (voice_extn_compress_voip_is_active(adev)) {
879 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700880 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530881 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700882 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800883 in_snd_device = voip_usecase->in_snd_device;
884 out_snd_device = voip_usecase->out_snd_device;
885 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800886 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800887 hfp_ucid = audio_extn_hfp_get_usecase();
888 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700889 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800890 in_snd_device = hfp_usecase->in_snd_device;
891 out_snd_device = hfp_usecase->out_snd_device;
892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 if (usecase->type == PCM_PLAYBACK) {
895 usecase->devices = usecase->stream.out->devices;
896 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700898 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800899 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 if (usecase->stream.out == adev->primary_output &&
901 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800902 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 select_devices(adev, adev->active_input->usecase);
904 }
905 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 } else if (usecase->type == PCM_CAPTURE) {
907 usecase->devices = usecase->stream.in->device;
908 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700910 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530911 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
912 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
913 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
914 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700915 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800916 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700917 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
918 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700919 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700921 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 }
923 }
924
925 if (out_snd_device == usecase->out_snd_device &&
926 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 return 0;
928 }
929
sangwoobc677242013-08-08 16:53:43 +0900930 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700931 out_snd_device, platform_get_snd_device_name(out_snd_device),
932 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800934 /*
935 * Limitation: While in call, to do a device switch we need to disable
936 * and enable both RX and TX devices though one of them is same as current
937 * device.
938 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700939 if ((usecase->type == VOICE_CALL) &&
940 (usecase->in_snd_device != SND_DEVICE_NONE) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700942 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700943 }
944
945 if (((usecase->type == VOICE_CALL) ||
946 (usecase->type == VOIP_CALL)) &&
947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
948 /* Disable sidetone only if voice/voip call already exists */
949 if (voice_is_call_state_active(adev) ||
950 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700951 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800952 }
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 /* Disable current sound devices */
955 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700956 disable_audio_route(adev, usecase);
957 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 }
964
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800965 /* Applicable only on the targets that has external modem.
966 * New device information should be sent to modem before enabling
967 * the devices to reduce in-call device switch time.
968 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700969 if ((usecase->type == VOICE_CALL) &&
970 (usecase->in_snd_device != SND_DEVICE_NONE) &&
971 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800972 status = platform_switch_voice_call_enable_device_config(adev->platform,
973 out_snd_device,
974 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700975 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800976
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 /* Enable new sound devices */
978 if (out_snd_device != SND_DEVICE_NONE) {
979 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
980 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700981 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 }
983
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700984 if (in_snd_device != SND_DEVICE_NONE) {
985 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700986 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988
Avinash Vaish71a8b972014-07-24 15:36:33 +0530989 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700990 status = platform_switch_voice_call_device_post(adev->platform,
991 out_snd_device,
992 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530993 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700994 /* Enable sidetone only if voice/voip call already exists */
995 if (voice_is_call_state_active(adev) ||
996 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700997 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530998 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800999
sangwoo170731f2013-06-08 15:36:36 +09001000 usecase->in_snd_device = in_snd_device;
1001 usecase->out_snd_device = out_snd_device;
1002
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301003 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001004 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301005 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001006 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301007 usecase->stream.out->flags,
1008 usecase->stream.out->format,
1009 usecase->stream.out->sample_rate,
1010 usecase->stream.out->bit_width,
1011 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001012 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001014
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001015 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001016
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001017 /* Applicable only on the targets that has external modem.
1018 * Enable device command should be sent to modem only after
1019 * enabling voice call mixer controls
1020 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001021 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001022 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1023 out_snd_device,
1024 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301025 ALOGD("%s: done",__func__);
1026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 return status;
1028}
1029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030static int stop_input_stream(struct stream_in *in)
1031{
1032 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 struct audio_usecase *uc_info;
1034 struct audio_device *adev = in->dev;
1035
Eric Laurentc8400632013-02-14 19:04:54 -08001036 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037
Eric Laurent994a6932013-07-17 11:51:42 -07001038 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040 uc_info = get_usecase_from_list(adev, in->usecase);
1041 if (uc_info == NULL) {
1042 ALOGE("%s: Could not find the usecase (%d) in the list",
1043 __func__, in->usecase);
1044 return -EINVAL;
1045 }
1046
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001047 /* Close in-call recording streams */
1048 voice_check_and_stop_incall_rec_usecase(adev, in);
1049
Eric Laurent150dbfe2013-02-27 14:31:02 -08001050 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001051 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052
1053 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001054 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001056 list_remove(&uc_info->list);
1057 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Eric Laurent994a6932013-07-17 11:51:42 -07001059 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 return ret;
1061}
1062
1063int start_input_stream(struct stream_in *in)
1064{
1065 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001066 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 struct audio_usecase *uc_info;
1068 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301069 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070
Mingming Yine62d7842013-10-25 16:26:03 -07001071 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301072 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1073 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001074
Naresh Tanniru80659832014-06-04 18:17:56 +05301075
1076 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301077 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301078 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301079 goto error_config;
1080 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301081
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001082 /* Check if source matches incall recording usecase criteria */
1083 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1084 if (ret)
1085 goto error_config;
1086 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001087 ALOGD("%s: Updated usecase(%d: %s)",
1088 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001089
Eric Laurentb23d5282013-05-14 15:27:20 -07001090 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 if (in->pcm_device_id < 0) {
1092 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1093 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001094 ret = -EINVAL;
1095 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097
1098 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001100
1101 if (!uc_info) {
1102 ret = -ENOMEM;
1103 goto error_config;
1104 }
1105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 uc_info->id = in->usecase;
1107 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001108 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 uc_info->devices = in->device;
1110 uc_info->in_snd_device = SND_DEVICE_NONE;
1111 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001113 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301114 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116
Eric Laurentc8400632013-02-14 19:04:54 -08001117 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001118 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1119
1120 unsigned int flags = PCM_IN;
1121 unsigned int pcm_open_retry_count = 0;
1122
1123 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1124 flags |= PCM_MMAP | PCM_NOIRQ;
1125 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1126 }
1127
1128 while (1) {
1129 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1130 flags, &in->config);
1131 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1132 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1133 if (in->pcm != NULL) {
1134 pcm_close(in->pcm);
1135 in->pcm = NULL;
1136 }
1137 if (pcm_open_retry_count-- == 0) {
1138 ret = -EIO;
1139 goto error_open;
1140 }
1141 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1142 continue;
1143 }
1144 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001145 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301146 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301147
Eric Laurent994a6932013-07-17 11:51:42 -07001148 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001149 return ret;
1150
1151error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301153 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001154
1155error_config:
1156 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001158
1159 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001160}
1161
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001162/* must be called with out->lock locked */
1163static int send_offload_cmd_l(struct stream_out* out, int command)
1164{
1165 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1166
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001167 if (!cmd) {
1168 ALOGE("failed to allocate mem for command 0x%x", command);
1169 return -ENOMEM;
1170 }
1171
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001172 ALOGVV("%s %d", __func__, command);
1173
1174 cmd->cmd = command;
1175 list_add_tail(&out->offload_cmd_list, &cmd->node);
1176 pthread_cond_signal(&out->offload_cond);
1177 return 0;
1178}
1179
1180/* must be called iwth out->lock locked */
1181static void stop_compressed_output_l(struct stream_out *out)
1182{
1183 out->offload_state = OFFLOAD_STATE_IDLE;
1184 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001185 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001186 if (out->compr != NULL) {
1187 compress_stop(out->compr);
1188 while (out->offload_thread_blocked) {
1189 pthread_cond_wait(&out->cond, &out->lock);
1190 }
1191 }
1192}
1193
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001194bool is_offload_usecase(audio_usecase_t uc_id)
1195{
1196 unsigned int i;
1197 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1198 if (uc_id == offload_usecases[i])
1199 return true;
1200 }
1201 return false;
1202}
1203
1204static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1205{
1206 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1207 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1208 char value[PROPERTY_VALUE_MAX] = {0};
1209
1210 property_get("audio.offload.multiple.enabled", value, NULL);
1211 if (!(atoi(value) || !strncmp("true", value, 4)))
1212 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1213
1214 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1215 for (i = 0; i < num_usecase; i++) {
1216 if (!(adev->offload_usecases_state & (0x1<<i))) {
1217 adev->offload_usecases_state |= 0x1 << i;
1218 ret = offload_usecases[i];
1219 break;
1220 }
1221 }
1222 ALOGV("%s: offload usecase is %d", __func__, ret);
1223 return ret;
1224}
1225
1226static void free_offload_usecase(struct audio_device *adev,
1227 audio_usecase_t uc_id)
1228{
1229 unsigned int i;
1230 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1231 if (offload_usecases[i] == uc_id) {
1232 adev->offload_usecases_state &= ~(0x1<<i);
1233 break;
1234 }
1235 }
1236 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1237}
1238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239static void *offload_thread_loop(void *context)
1240{
1241 struct stream_out *out = (struct stream_out *) context;
1242 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001243 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001245 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1246 set_sched_policy(0, SP_FOREGROUND);
1247 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1248
1249 ALOGV("%s", __func__);
1250 pthread_mutex_lock(&out->lock);
1251 for (;;) {
1252 struct offload_cmd *cmd = NULL;
1253 stream_callback_event_t event;
1254 bool send_callback = false;
1255
1256 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1257 __func__, list_empty(&out->offload_cmd_list),
1258 out->offload_state);
1259 if (list_empty(&out->offload_cmd_list)) {
1260 ALOGV("%s SLEEPING", __func__);
1261 pthread_cond_wait(&out->offload_cond, &out->lock);
1262 ALOGV("%s RUNNING", __func__);
1263 continue;
1264 }
1265
1266 item = list_head(&out->offload_cmd_list);
1267 cmd = node_to_item(item, struct offload_cmd, node);
1268 list_remove(item);
1269
1270 ALOGVV("%s STATE %d CMD %d out->compr %p",
1271 __func__, out->offload_state, cmd->cmd, out->compr);
1272
1273 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1274 free(cmd);
1275 break;
1276 }
1277
1278 if (out->compr == NULL) {
1279 ALOGE("%s: Compress handle is NULL", __func__);
1280 pthread_cond_signal(&out->cond);
1281 continue;
1282 }
1283 out->offload_thread_blocked = true;
1284 pthread_mutex_unlock(&out->lock);
1285 send_callback = false;
1286 switch(cmd->cmd) {
1287 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001290 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001291 send_callback = true;
1292 event = STREAM_CBK_EVENT_WRITE_READY;
1293 break;
1294 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001295 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301296 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001297 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301298 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001299 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301300 if (ret < 0)
1301 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301302 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301303 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001304 compress_drain(out->compr);
1305 else
1306 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301307 if (ret != -ENETRESET) {
1308 send_callback = true;
1309 event = STREAM_CBK_EVENT_DRAIN_READY;
1310 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1311 } else
1312 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 break;
1314 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001315 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001316 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001317 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 send_callback = true;
1319 event = STREAM_CBK_EVENT_DRAIN_READY;
1320 break;
1321 default:
1322 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1323 break;
1324 }
1325 pthread_mutex_lock(&out->lock);
1326 out->offload_thread_blocked = false;
1327 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001328 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001329 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001330 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001331 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 free(cmd);
1333 }
1334
1335 pthread_cond_signal(&out->cond);
1336 while (!list_empty(&out->offload_cmd_list)) {
1337 item = list_head(&out->offload_cmd_list);
1338 list_remove(item);
1339 free(node_to_item(item, struct offload_cmd, node));
1340 }
1341 pthread_mutex_unlock(&out->lock);
1342
1343 return NULL;
1344}
1345
1346static int create_offload_callback_thread(struct stream_out *out)
1347{
1348 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1349 list_init(&out->offload_cmd_list);
1350 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1351 offload_thread_loop, out);
1352 return 0;
1353}
1354
1355static int destroy_offload_callback_thread(struct stream_out *out)
1356{
1357 pthread_mutex_lock(&out->lock);
1358 stop_compressed_output_l(out);
1359 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1360
1361 pthread_mutex_unlock(&out->lock);
1362 pthread_join(out->offload_thread, (void **) NULL);
1363 pthread_cond_destroy(&out->offload_cond);
1364
1365 return 0;
1366}
1367
Eric Laurent07eeafd2013-10-06 12:52:49 -07001368static bool allow_hdmi_channel_config(struct audio_device *adev)
1369{
1370 struct listnode *node;
1371 struct audio_usecase *usecase;
1372 bool ret = true;
1373
1374 list_for_each(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
1376 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1377 /*
1378 * If voice call is already existing, do not proceed further to avoid
1379 * disabling/enabling both RX and TX devices, CSD calls, etc.
1380 * Once the voice call done, the HDMI channels can be configured to
1381 * max channels of remaining use cases.
1382 */
1383 if (usecase->id == USECASE_VOICE_CALL) {
1384 ALOGD("%s: voice call is active, no change in HDMI channels",
1385 __func__);
1386 ret = false;
1387 break;
1388 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1389 ALOGD("%s: multi channel playback is active, "
1390 "no change in HDMI channels", __func__);
1391 ret = false;
1392 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001393 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001394 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001395 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1396 ", no change in HDMI channels", __func__,
1397 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001398 ret = false;
1399 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001400 }
1401 }
1402 }
1403 return ret;
1404}
1405
1406static int check_and_set_hdmi_channels(struct audio_device *adev,
1407 unsigned int channels)
1408{
1409 struct listnode *node;
1410 struct audio_usecase *usecase;
1411
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001412 unsigned int supported_channels = platform_edid_get_max_channels(
1413 adev->platform);
1414 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001415 /* Check if change in HDMI channel config is allowed */
1416 if (!allow_hdmi_channel_config(adev))
1417 return 0;
1418
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001419 if (channels > supported_channels)
1420 channels = supported_channels;
1421
Eric Laurent07eeafd2013-10-06 12:52:49 -07001422 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001423 ALOGD("%s: Requested channels are same as current channels(%d)",
1424 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425 return 0;
1426 }
1427
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001428 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001430 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 adev->cur_hdmi_channels = channels;
1432
1433 /*
1434 * Deroute all the playback streams routed to HDMI so that
1435 * the back end is deactivated. Note that backend will not
1436 * be deactivated if any one stream is connected to it.
1437 */
1438 list_for_each(node, &adev->usecase_list) {
1439 usecase = node_to_item(node, struct audio_usecase, list);
1440 if (usecase->type == PCM_PLAYBACK &&
1441 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001442 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001443 }
1444 }
1445
1446 /*
1447 * Enable all the streams disabled above. Now the HDMI backend
1448 * will be activated with new channel configuration
1449 */
1450 list_for_each(node, &adev->usecase_list) {
1451 usecase = node_to_item(node, struct audio_usecase, list);
1452 if (usecase->type == PCM_PLAYBACK &&
1453 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001454 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001455 }
1456 }
1457
1458 return 0;
1459}
1460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461static int stop_output_stream(struct stream_out *out)
1462{
1463 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 struct audio_usecase *uc_info;
1465 struct audio_device *adev = out->dev;
1466
Eric Laurent994a6932013-07-17 11:51:42 -07001467 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 uc_info = get_usecase_from_list(adev, out->usecase);
1470 if (uc_info == NULL) {
1471 ALOGE("%s: Could not find the usecase (%d) in the list",
1472 __func__, out->usecase);
1473 return -EINVAL;
1474 }
1475
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001476 if (is_offload_usecase(out->usecase) &&
1477 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001478 if (adev->visualizer_stop_output != NULL)
1479 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001480
1481 audio_extn_dts_remove_state_notifier_node(out->usecase);
1482
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001483 if (adev->offload_effects_stop_output != NULL)
1484 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1485 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001486
Eric Laurent150dbfe2013-02-27 14:31:02 -08001487 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001488 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001489
1490 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001493 list_remove(&uc_info->list);
1494 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001496 if (is_offload_usecase(out->usecase) &&
1497 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1498 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1499 ALOGV("Disable passthrough , reset mixer to pcm");
1500 /* NO_PASSTHROUGH */
1501 out->compr_config.codec->compr_passthr = 0;
1502 audio_extn_dolby_set_hdmi_config(adev, out);
1503 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1504 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001505 /* Must be called after removing the usecase from list */
1506 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1507 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1508
Eric Laurent994a6932013-07-17 11:51:42 -07001509 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 return ret;
1511}
1512
1513int start_output_stream(struct stream_out *out)
1514{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001516 int sink_channels = 0;
1517 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 struct audio_usecase *uc_info;
1519 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301520 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001522 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1523 ret = -EINVAL;
1524 goto error_config;
1525 }
1526
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301527 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1528 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1529 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301530
Naresh Tanniru80659832014-06-04 18:17:56 +05301531 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301532 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301533 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301534 goto error_config;
1535 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301536
Eric Laurentb23d5282013-05-14 15:27:20 -07001537 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 if (out->pcm_device_id < 0) {
1539 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1540 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001541 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001542 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 }
1544
1545 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001546
1547 if (!uc_info) {
1548 ret = -ENOMEM;
1549 goto error_config;
1550 }
1551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 uc_info->id = out->usecase;
1553 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001554 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 uc_info->devices = out->devices;
1556 uc_info->in_snd_device = SND_DEVICE_NONE;
1557 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001558 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001559 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 if (is_offload_usecase(out->usecase)) {
1561 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001562 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1563 }
1564 }
Mingming Yin9c041392014-05-01 15:37:31 -07001565 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1566 if (!strncmp("true", prop_value, 4)) {
1567 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001568 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1569 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001570 check_and_set_hdmi_channels(adev, sink_channels);
1571 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001572 if (is_offload_usecase(out->usecase)) {
1573 unsigned int ch_count = out->compr_config.codec->ch_in;
1574 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1575 /* backend channel config for passthrough stream is stereo */
1576 ch_count = 2;
1577 check_and_set_hdmi_channels(adev, ch_count);
1578 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001579 check_and_set_hdmi_channels(adev, out->config.channels);
1580 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001581 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001582 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001583 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 select_devices(adev, out->usecase);
1586
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001587 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1588 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001589 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001590 unsigned int flags = PCM_OUT;
1591 unsigned int pcm_open_retry_count = 0;
1592 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1593 flags |= PCM_MMAP | PCM_NOIRQ;
1594 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1595 } else
1596 flags |= PCM_MONOTONIC;
1597
1598 while (1) {
1599 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1600 flags, &out->config);
1601 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1602 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1603 if (out->pcm != NULL) {
1604 pcm_close(out->pcm);
1605 out->pcm = NULL;
1606 }
1607 if (pcm_open_retry_count-- == 0) {
1608 ret = -EIO;
1609 goto error_open;
1610 }
1611 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1612 continue;
1613 }
1614 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001615 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001616 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1617 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001619 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1620 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001622 out->compr = compress_open(adev->snd_card,
1623 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001624 COMPRESS_IN, &out->compr_config);
1625 if (out->compr && !is_compress_ready(out->compr)) {
1626 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1627 compress_close(out->compr);
1628 out->compr = NULL;
1629 ret = -EIO;
1630 goto error_open;
1631 }
1632 if (out->offload_callback)
1633 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001634
Fred Oh3f43e742015-03-04 18:42:34 -08001635 /* Since small bufs uses blocking writes, a write will be blocked
1636 for the default max poll time (20s) in the event of an SSR.
1637 Reduce the poll time to observe and deal with SSR faster.
1638 */
1639 if (out->use_small_bufs) {
1640 compress_set_max_poll_wait(out->compr, 1000);
1641 }
1642
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001643 audio_extn_dts_create_state_notifier_node(out->usecase);
1644 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1645 popcount(out->channel_mask),
1646 out->playback_started);
1647
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001648#ifdef DS1_DOLBY_DDP_ENABLED
1649 if (audio_extn_is_dolby_format(out->format))
1650 audio_extn_dolby_send_ddp_endp_params(adev);
1651#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001652 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1653 if (adev->visualizer_start_output != NULL)
1654 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1655 if (adev->offload_effects_start_output != NULL)
1656 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001657 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001658 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 }
Eric Laurent994a6932013-07-17 11:51:42 -07001660 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001664error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001665 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666}
1667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668static int check_input_parameters(uint32_t sample_rate,
1669 audio_format_t format,
1670 int channel_count)
1671{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001672 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001674 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001675 !voice_extn_compress_voip_is_format_supported(format) &&
1676 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001677
1678 switch (channel_count) {
1679 case 1:
1680 case 2:
1681 case 6:
1682 break;
1683 default:
1684 ret = -EINVAL;
1685 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
1687 switch (sample_rate) {
1688 case 8000:
1689 case 11025:
1690 case 12000:
1691 case 16000:
1692 case 22050:
1693 case 24000:
1694 case 32000:
1695 case 44100:
1696 case 48000:
1697 break;
1698 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001699 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
1701
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001702 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703}
1704
1705static size_t get_input_buffer_size(uint32_t sample_rate,
1706 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001707 int channel_count,
1708 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709{
1710 size_t size = 0;
1711
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001712 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1713 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001715 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001716 if (is_low_latency)
1717 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001718 /* ToDo: should use frame_size computed based on the format and
1719 channel_count here. */
1720 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001722 /* make sure the size is multiple of 32 bytes
1723 * At 48 kHz mono 16-bit PCM:
1724 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1725 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1726 */
1727 size += 0x1f;
1728 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001729
1730 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731}
1732
1733static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1734{
1735 struct stream_out *out = (struct stream_out *)stream;
1736
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738}
1739
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001740static int out_set_sample_rate(struct audio_stream *stream __unused,
1741 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742{
1743 return -ENOSYS;
1744}
1745
1746static size_t out_get_buffer_size(const struct audio_stream *stream)
1747{
1748 struct stream_out *out = (struct stream_out *)stream;
1749
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001750 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001752 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1753 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001755 return out->config.period_size *
1756 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757}
1758
1759static uint32_t out_get_channels(const struct audio_stream *stream)
1760{
1761 struct stream_out *out = (struct stream_out *)stream;
1762
1763 return out->channel_mask;
1764}
1765
1766static audio_format_t out_get_format(const struct audio_stream *stream)
1767{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768 struct stream_out *out = (struct stream_out *)stream;
1769
1770 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771}
1772
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001773static int out_set_format(struct audio_stream *stream __unused,
1774 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775{
1776 return -ENOSYS;
1777}
1778
1779static int out_standby(struct audio_stream *stream)
1780{
1781 struct stream_out *out = (struct stream_out *)stream;
1782 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301784 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1785 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001786 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1787 /* Ignore standby in case of voip call because the voip output
1788 * stream is closed in adev_close_output_stream()
1789 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301790 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001791 return 0;
1792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001796 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001798 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 if (out->pcm) {
1800 pcm_close(out->pcm);
1801 out->pcm = NULL;
1802 }
1803 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001804 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001806 out->gapless_mdata.encoder_delay = 0;
1807 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 if (out->compr != NULL) {
1809 compress_close(out->compr);
1810 out->compr = NULL;
1811 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001812 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001814 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
1816 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001817 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 return 0;
1819}
1820
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001821static int out_dump(const struct audio_stream *stream __unused,
1822 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823{
1824 return 0;
1825}
1826
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1828{
1829 int ret = 0;
1830 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001831 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001832
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001833 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001834 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835 return -EINVAL;
1836 }
1837
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301838 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001839
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1841 if(ret >= 0)
1842 is_meta_data_params = true;
1843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301844 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001845 is_meta_data_params = true;
1846 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301847 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001848 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1850 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001851 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301852 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1855 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001856 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301857 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001858 }
1859
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001860 if(!is_meta_data_params) {
1861 ALOGV("%s: Not gapless meta data params", __func__);
1862 return 0;
1863 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 out->send_new_metadata = 1;
1865 ALOGV("%s new encoder delay %u and padding %u", __func__,
1866 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1867
1868 return 0;
1869}
1870
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001871static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1872{
1873 return out == adev->primary_output || out == adev->voice_tx_output;
1874}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1877{
1878 struct stream_out *out = (struct stream_out *)stream;
1879 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001880 struct audio_usecase *usecase;
1881 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 struct str_parms *parms;
1883 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001884 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001885 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886
sangwoobc677242013-08-08 16:53:43 +09001887 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301890 if (!parms)
1891 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001892 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1893 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001896 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301899 * When HDMI cable is unplugged/usb hs is disconnected the
1900 * music playback is paused and the policy manager sends routing=0
1901 * But the audioflingercontinues to write data until standby time
1902 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 * Avoid this by routing audio to speaker until standby.
1904 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301905 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1906 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001908 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1909 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001910 }
1911
1912 /*
1913 * select_devices() call below switches all the usecases on the same
1914 * backend to the new device. Refer to check_usecases_codec_backend() in
1915 * the select_devices(). But how do we undo this?
1916 *
1917 * For example, music playback is active on headset (deep-buffer usecase)
1918 * and if we go to ringtones and select a ringtone, low-latency usecase
1919 * will be started on headset+speaker. As we can't enable headset+speaker
1920 * and headset devices at the same time, select_devices() switches the music
1921 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1922 * So when the ringtone playback is completed, how do we undo the same?
1923 *
1924 * We are relying on the out_set_parameters() call on deep-buffer output,
1925 * once the ringtone playback is ended.
1926 * NOTE: We should not check if the current devices are same as new devices.
1927 * Because select_devices() must be called to switch back the music
1928 * playback to headset.
1929 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001930 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001931 out->devices = val;
1932
1933 if (!out->standby)
1934 select_devices(adev, out->usecase);
1935
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001936 if (output_drives_call(adev, out)) {
1937 if(!voice_is_in_call(adev)) {
1938 if (adev->mode == AUDIO_MODE_IN_CALL) {
1939 adev->current_call_output = out;
1940 ret = voice_start_call(adev);
1941 }
1942 } else {
1943 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001944 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001945 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001946 }
1947 }
1948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001950 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001952
1953 if (out == adev->primary_output) {
1954 pthread_mutex_lock(&adev->lock);
1955 audio_extn_set_parameters(adev, parms);
1956 pthread_mutex_unlock(&adev->lock);
1957 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001958 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001959 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001960 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001961
1962 audio_extn_dts_create_state_notifier_node(out->usecase);
1963 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1964 popcount(out->channel_mask),
1965 out->playback_started);
1966
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001967 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001968 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301971error:
Eric Laurent994a6932013-07-17 11:51:42 -07001972 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 return ret;
1974}
1975
1976static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1977{
1978 struct stream_out *out = (struct stream_out *)stream;
1979 struct str_parms *query = str_parms_create_str(keys);
1980 char *str;
1981 char value[256];
1982 struct str_parms *reply = str_parms_create();
1983 size_t i, j;
1984 int ret;
1985 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001986
1987 if (!query || !reply) {
1988 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1989 return NULL;
1990 }
1991
Eric Laurent994a6932013-07-17 11:51:42 -07001992 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1994 if (ret >= 0) {
1995 value[0] = '\0';
1996 i = 0;
1997 while (out->supported_channel_masks[i] != 0) {
1998 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1999 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2000 if (!first) {
2001 strcat(value, "|");
2002 }
2003 strcat(value, out_channels_name_to_enum_table[j].name);
2004 first = false;
2005 break;
2006 }
2007 }
2008 i++;
2009 }
2010 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2011 str = str_parms_to_str(reply);
2012 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002013 voice_extn_out_get_parameters(out, query, reply);
2014 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002015 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002016 free(str);
2017 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002020
2021 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2022 if (ret >= 0) {
2023 value[0] = '\0';
2024 i = 0;
2025 first = true;
2026 while (out->supported_formats[i] != 0) {
2027 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2028 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2029 if (!first) {
2030 strcat(value, "|");
2031 }
2032 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2033 first = false;
2034 break;
2035 }
2036 }
2037 i++;
2038 }
2039 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2040 str = str_parms_to_str(reply);
2041 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 str_parms_destroy(query);
2043 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002044 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 return str;
2046}
2047
2048static uint32_t out_get_latency(const struct audio_stream_out *stream)
2049{
2050 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002051 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Alexy Josephaa54c872014-12-03 02:46:47 -08002053 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002054 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002055 } else {
2056 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002058 }
2059
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302060 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002061 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062}
2063
2064static int out_set_volume(struct audio_stream_out *stream, float left,
2065 float right)
2066{
Eric Laurenta9024de2013-04-04 09:19:12 -07002067 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 int volume[2];
2069
Eric Laurenta9024de2013-04-04 09:19:12 -07002070 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2071 /* only take left channel into account: the API is for stereo anyway */
2072 out->muted = (left == 0.0f);
2073 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002074 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002075 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2076 /*
2077 * Set mute or umute on HDMI passthrough stream.
2078 * Only take left channel into account.
2079 * Mute is 0 and unmute 1
2080 */
2081 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2082 } else {
2083 char mixer_ctl_name[128];
2084 struct audio_device *adev = out->dev;
2085 struct mixer_ctl *ctl;
2086 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002087 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002089 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2090 "Compress Playback %d Volume", pcm_device_id);
2091 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2092 if (!ctl) {
2093 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2094 __func__, mixer_ctl_name);
2095 return -EINVAL;
2096 }
2097 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2098 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2099 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2100 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002102 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 return -ENOSYS;
2105}
2106
2107static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2108 size_t bytes)
2109{
2110 struct stream_out *out = (struct stream_out *)stream;
2111 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302112 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002113 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302116
Naresh Tanniru80659832014-06-04 18:17:56 +05302117 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002118 // increase written size during SSR to avoid mismatch
2119 // with the written frames count in AF
2120 if (!is_offload_usecase(out->usecase))
2121 out->written += bytes / (out->config.channels * sizeof(short));
2122
Naresh Tanniru80659832014-06-04 18:17:56 +05302123 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302124 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302125 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302126 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002127 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 //during SSR for compress usecase we should return error to flinger
2129 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2130 pthread_mutex_unlock(&out->lock);
2131 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302132 }
2133 }
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002136 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002137 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002138 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2139 ret = voice_extn_compress_voip_start_output_stream(out);
2140 else
2141 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002142 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002145 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 goto exit;
2147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002150 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002151 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002153 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2155 out->send_new_metadata = 0;
2156 }
2157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302159 if (ret < 0)
2160 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002161 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002162 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302163 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 } else if (-ENETRESET == ret) {
2166 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2167 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2168 pthread_mutex_unlock(&out->lock);
2169 out_standby(&out->stream.common);
2170 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302172 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002174 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 out->playback_started = 1;
2176 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002177
2178 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2179 popcount(out->channel_mask),
2180 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
2182 pthread_mutex_unlock(&out->lock);
2183 return ret;
2184 } else {
2185 if (out->pcm) {
2186 if (out->muted)
2187 memset((void *)buffer, 0, bytes);
2188 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002189 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2190 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2191 else
2192 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302193 if (ret < 0)
2194 ret = -errno;
2195 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002196 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 }
2199
2200exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302201 /* ToDo: There may be a corner case when SSR happens back to back during
2202 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302203 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205 }
2206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 pthread_mutex_unlock(&out->lock);
2208
2209 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002210 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002211 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302212 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302213 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302214 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302215 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302216 out->standby = true;
2217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002219 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 out_get_sample_rate(&out->stream.common));
2221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 }
2223 return bytes;
2224}
2225
2226static int out_get_render_position(const struct audio_stream_out *stream,
2227 uint32_t *dsp_frames)
2228{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302230 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002231
2232 if (dsp_frames == NULL)
2233 return -EINVAL;
2234
2235 *dsp_frames = 0;
2236 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002237 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 pthread_mutex_lock(&out->lock);
2239 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302240 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302242 if (ret < 0)
2243 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 ALOGVV("%s rendered frames %d sample_rate %d",
2245 __func__, *dsp_frames, out->sample_rate);
2246 }
2247 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302248 if (-ENETRESET == ret) {
2249 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2250 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2251 return -EINVAL;
2252 } else if(ret < 0) {
2253 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2254 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302255 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2256 /*
2257 * Handle corner case where compress session is closed during SSR
2258 * and timestamp is queried
2259 */
2260 ALOGE(" ERROR: sound card not active, return error");
2261 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302262 } else {
2263 return 0;
2264 }
Zhou Song32a556e2015-05-05 10:46:56 +08002265 } else if (audio_is_linear_pcm(out->format)) {
2266 *dsp_frames = out->written;
2267 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 } else
2269 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270}
2271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002272static int out_add_audio_effect(const struct audio_stream *stream __unused,
2273 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274{
2275 return 0;
2276}
2277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002278static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2279 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280{
2281 return 0;
2282}
2283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002284static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2285 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286{
2287 return -EINVAL;
2288}
2289
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002290static int out_get_presentation_position(const struct audio_stream_out *stream,
2291 uint64_t *frames, struct timespec *timestamp)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002296
2297 pthread_mutex_lock(&out->lock);
2298
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002299 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002300 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302301 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002302 &out->sample_rate);
2303 ALOGVV("%s rendered frames %ld sample_rate %d",
2304 __func__, dsp_frames, out->sample_rate);
2305 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302306 if (ret < 0)
2307 ret = -errno;
2308 if (-ENETRESET == ret) {
2309 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2310 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2311 ret = -EINVAL;
2312 } else
2313 ret = 0;
2314
Eric Laurent949a0892013-09-20 09:20:13 -07002315 /* this is the best we can do */
2316 clock_gettime(CLOCK_MONOTONIC, timestamp);
2317 }
2318 } else {
2319 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002321 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2322 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002323 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002324 // This adjustment accounts for buffering after app processor.
2325 // It is based on estimated DSP latency per use case, rather than exact.
2326 signed_frames -=
2327 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2328
Eric Laurent949a0892013-09-20 09:20:13 -07002329 // It would be unusual for this value to be negative, but check just in case ...
2330 if (signed_frames >= 0) {
2331 *frames = signed_frames;
2332 ret = 0;
2333 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002334 }
2335 }
2336 }
2337
2338 pthread_mutex_unlock(&out->lock);
2339
2340 return ret;
2341}
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343static int out_set_callback(struct audio_stream_out *stream,
2344 stream_callback_t callback, void *cookie)
2345{
2346 struct stream_out *out = (struct stream_out *)stream;
2347
2348 ALOGV("%s", __func__);
2349 pthread_mutex_lock(&out->lock);
2350 out->offload_callback = callback;
2351 out->offload_cookie = cookie;
2352 pthread_mutex_unlock(&out->lock);
2353 return 0;
2354}
2355
2356static int out_pause(struct audio_stream_out* stream)
2357{
2358 struct stream_out *out = (struct stream_out *)stream;
2359 int status = -ENOSYS;
2360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002362 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 pthread_mutex_lock(&out->lock);
2364 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302365 struct audio_device *adev = out->dev;
2366 int snd_scard_state = get_snd_card_state(adev);
2367
2368 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2369 status = compress_pause(out->compr);
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302373 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374 audio_extn_dts_notify_playback_state(out->usecase, 0,
2375 out->sample_rate, popcount(out->channel_mask),
2376 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 }
2378 pthread_mutex_unlock(&out->lock);
2379 }
2380 return status;
2381}
2382
2383static int out_resume(struct audio_stream_out* stream)
2384{
2385 struct stream_out *out = (struct stream_out *)stream;
2386 int status = -ENOSYS;
2387 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002388 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002389 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 status = 0;
2391 pthread_mutex_lock(&out->lock);
2392 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
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_resume(out->compr);
2398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002400
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302401 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2403 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 }
2405 pthread_mutex_unlock(&out->lock);
2406 }
2407 return status;
2408}
2409
2410static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2411{
2412 struct stream_out *out = (struct stream_out *)stream;
2413 int status = -ENOSYS;
2414 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002415 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 pthread_mutex_lock(&out->lock);
2417 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2418 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2419 else
2420 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2421 pthread_mutex_unlock(&out->lock);
2422 }
2423 return status;
2424}
2425
2426static int out_flush(struct audio_stream_out* stream)
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002431 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 pthread_mutex_lock(&out->lock);
2433 stop_compressed_output_l(out);
2434 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002435 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 return 0;
2437 }
2438 return -ENOSYS;
2439}
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441/** audio_stream_in implementation **/
2442static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->config.rate;
2447}
2448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002449static int in_set_sample_rate(struct audio_stream *stream __unused,
2450 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451{
2452 return -ENOSYS;
2453}
2454
2455static size_t in_get_buffer_size(const struct audio_stream *stream)
2456{
2457 struct stream_in *in = (struct stream_in *)stream;
2458
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2460 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002461 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2462 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002463
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002464 return in->config.period_size *
2465 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466}
2467
2468static uint32_t in_get_channels(const struct audio_stream *stream)
2469{
2470 struct stream_in *in = (struct stream_in *)stream;
2471
2472 return in->channel_mask;
2473}
2474
2475static audio_format_t in_get_format(const struct audio_stream *stream)
2476{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 struct stream_in *in = (struct stream_in *)stream;
2478
2479 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002482static int in_set_format(struct audio_stream *stream __unused,
2483 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return -ENOSYS;
2486}
2487
2488static int in_standby(struct audio_stream *stream)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491 struct audio_device *adev = in->dev;
2492 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302493 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2494 stream, in->usecase, use_case_table[in->usecase]);
2495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2497 /* Ignore standby in case of voip call because the voip input
2498 * stream is closed in adev_close_input_stream()
2499 */
2500 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2501 return status;
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002505 if (!in->standby && in->is_st_session) {
2506 ALOGD("%s: sound trigger pcm stop lab", __func__);
2507 audio_extn_sound_trigger_stop_lab(in);
2508 in->standby = 1;
2509 }
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002512 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002514 if (in->pcm) {
2515 pcm_close(in->pcm);
2516 in->pcm = NULL;
2517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
2521 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002522 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 return status;
2524}
2525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002526static int in_dump(const struct audio_stream *stream __unused,
2527 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528{
2529 return 0;
2530}
2531
2532static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535 struct audio_device *adev = in->dev;
2536 struct str_parms *parms;
2537 char *str;
2538 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002539 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302541 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 parms = str_parms_create_str(kvpairs);
2543
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302544 if (!parms)
2545 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002548
2549 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2550 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 val = atoi(value);
2552 /* no audio source uses val == 0 */
2553 if ((in->source != val) && (val != 0)) {
2554 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002555 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2556 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2557 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2558 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002559 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002560 err = voice_extn_compress_voip_open_input_stream(in);
2561 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002562 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002563 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002564 }
2565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
2567 }
2568
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002569 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2570 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002572 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 in->device = val;
2574 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002575 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002576 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578 }
2579
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002580done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002582 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
2584 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302585error:
Eric Laurent994a6932013-07-17 11:51:42 -07002586 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 return ret;
2588}
2589
2590static char* in_get_parameters(const struct audio_stream *stream,
2591 const char *keys)
2592{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 struct stream_in *in = (struct stream_in *)stream;
2594 struct str_parms *query = str_parms_create_str(keys);
2595 char *str;
2596 char value[256];
2597 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002598
2599 if (!query || !reply) {
2600 ALOGE("in_get_parameters: failed to create query or reply");
2601 return NULL;
2602 }
2603
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002604 ALOGV("%s: enter: keys - %s", __func__, keys);
2605
2606 voice_extn_in_get_parameters(in, query, reply);
2607
2608 str = str_parms_to_str(reply);
2609 str_parms_destroy(query);
2610 str_parms_destroy(reply);
2611
2612 ALOGV("%s: exit: returns - %s", __func__, str);
2613 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002616static int in_set_gain(struct audio_stream_in *stream __unused,
2617 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618{
2619 return 0;
2620}
2621
2622static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2623 size_t bytes)
2624{
2625 struct stream_in *in = (struct stream_in *)stream;
2626 struct audio_device *adev = in->dev;
2627 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302628 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302631
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002632 if (in->is_st_session) {
2633 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2634 /* Read from sound trigger HAL */
2635 audio_extn_sound_trigger_read(in, buffer, bytes);
2636 pthread_mutex_unlock(&in->lock);
2637 return bytes;
2638 }
2639
2640 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2641 ALOGD(" %s: sound card is not active/SSR state", __func__);
2642 ret= -EIO;;
2643 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302644 }
2645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002647 pthread_mutex_lock(&adev->lock);
2648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2649 ret = voice_extn_compress_voip_start_input_stream(in);
2650 else
2651 ret = start_input_stream(in);
2652 pthread_mutex_unlock(&adev->lock);
2653 if (ret != 0) {
2654 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
2656 in->standby = 0;
2657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
2659 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002660 if (audio_extn_ssr_get_enabled() &&
2661 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002662 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002663 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2664 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002665 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2666 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002667 else
2668 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302669 if (ret < 0)
2670 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672
2673 /*
2674 * Instead of writing zeroes here, we could trust the hardware
2675 * to always provide zeroes when muted.
2676 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302677 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2678 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 memset(buffer, 0, bytes);
2680
2681exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302682 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302683 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002684 if (-ENETRESET == ret)
2685 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 pthread_mutex_unlock(&in->lock);
2688
2689 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302690 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302691 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302692 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302693 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302694 in->standby = true;
2695 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302696 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002698 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002699 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302700 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 }
2702 return bytes;
2703}
2704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002705static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
2707 return 0;
2708}
2709
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710static int add_remove_audio_effect(const struct audio_stream *stream,
2711 effect_handle_t effect,
2712 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002714 struct stream_in *in = (struct stream_in *)stream;
2715 int status = 0;
2716 effect_descriptor_t desc;
2717
2718 status = (*effect)->get_descriptor(effect, &desc);
2719 if (status != 0)
2720 return status;
2721
2722 pthread_mutex_lock(&in->lock);
2723 pthread_mutex_lock(&in->dev->lock);
2724 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2725 in->enable_aec != enable &&
2726 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2727 in->enable_aec = enable;
2728 if (!in->standby)
2729 select_devices(in->dev, in->usecase);
2730 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002731 if (in->enable_ns != enable &&
2732 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2733 in->enable_ns = enable;
2734 if (!in->standby)
2735 select_devices(in->dev, in->usecase);
2736 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002737 pthread_mutex_unlock(&in->dev->lock);
2738 pthread_mutex_unlock(&in->lock);
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 return 0;
2741}
2742
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002743static int in_add_audio_effect(const struct audio_stream *stream,
2744 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
Eric Laurent994a6932013-07-17 11:51:42 -07002746 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002747 return add_remove_audio_effect(stream, effect, true);
2748}
2749
2750static int in_remove_audio_effect(const struct audio_stream *stream,
2751 effect_handle_t effect)
2752{
Eric Laurent994a6932013-07-17 11:51:42 -07002753 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002754 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755}
2756
2757static int adev_open_output_stream(struct audio_hw_device *dev,
2758 audio_io_handle_t handle,
2759 audio_devices_t devices,
2760 audio_output_flags_t flags,
2761 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002762 struct audio_stream_out **stream_out,
2763 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
2765 struct audio_device *adev = (struct audio_device *)dev;
2766 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002767 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002768 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302771
2772 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2773 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2774 ALOGE(" sound card is not active rejecting compress output open request");
2775 return -EINVAL;
2776 }
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2779
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302780 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2781 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2782 devices, flags, &out->stream);
2783
2784
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002785 if (!out) {
2786 return -ENOMEM;
2787 }
2788
Haynes Mathew George204045b2015-02-25 20:32:03 -08002789 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2790 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 if (devices == AUDIO_DEVICE_NONE)
2793 devices = AUDIO_DEVICE_OUT_SPEAKER;
2794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 out->flags = flags;
2796 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002797 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002798 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->sample_rate = config->sample_rate;
2800 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2801 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002802 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002803 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002804 out->non_blocking = 0;
2805 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806
2807 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002808 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2809 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002810 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2811 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2812
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002813 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002814 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2815 ret = read_hdmi_channel_masks(out);
2816
2817 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2818 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002819 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002820 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002821 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002822
2823 if (config->sample_rate == 0)
2824 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2825 if (config->channel_mask == 0)
2826 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2827
2828 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2831 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002833 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002835 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2836 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002837 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002838 ret = voice_extn_compress_voip_open_output_stream(out);
2839 if (ret != 0) {
2840 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2841 __func__, ret);
2842 goto error_open;
2843 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2845 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2846 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2847 ALOGE("%s: Unsupported Offload information", __func__);
2848 ret = -EINVAL;
2849 goto error_open;
2850 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002851
2852 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2853 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2854 ALOGV("read and update_pass through formats");
2855 ret = audio_extn_dolby_update_passt_formats(adev, out);
2856 if(ret != 0) {
2857 goto error_open;
2858 }
2859 if(config->offload_info.format == 0)
2860 config->offload_info.format = out->supported_formats[0];
2861 }
2862
Mingming Yin90310102013-11-13 16:57:00 -08002863 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002864 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 ALOGE("%s: Unsupported audio format", __func__);
2866 ret = -EINVAL;
2867 goto error_open;
2868 }
2869
2870 out->compr_config.codec = (struct snd_codec *)
2871 calloc(1, sizeof(struct snd_codec));
2872
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002873 if (!out->compr_config.codec) {
2874 ret = -ENOMEM;
2875 goto error_open;
2876 }
2877
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002878 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 if (config->offload_info.channel_mask)
2880 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002881 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002883 config->offload_info.channel_mask = config->channel_mask;
2884 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002885 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->sample_rate = config->offload_info.sample_rate;
2887
2888 out->stream.set_callback = out_set_callback;
2889 out->stream.pause = out_pause;
2890 out->stream.resume = out_resume;
2891 out->stream.drain = out_drain;
2892 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002893 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002895 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002896 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002897 audio_extn_dolby_get_snd_codec_id(adev, out,
2898 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002899 else
2900 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat2ec445f2015-07-23 18:02:31 +05302902 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002903 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002904 platform_get_pcm_offload_buffer_size(&config->offload_info);
2905 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2906 out->compr_config.fragment_size =
2907 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002908 } else {
2909 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002910 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002911 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2913 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002914 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->compr_config.codec->bit_rate =
2916 config->offload_info.bit_rate;
2917 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002918 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302920 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002921 /*TODO: Do we need to change it for passthrough */
2922 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002923
Manish Dewangana6fc5442015-08-24 20:30:31 +05302924 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2925 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2926 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2927 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002928 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2929 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002930 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002931 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2932
Mingming Yin3ee55c62014-08-04 14:23:35 -07002933 if (out->bit_width == 24) {
2934 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2935 }
2936
Amit Shekhar6f461b12014-08-01 14:52:58 -07002937 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302938 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2941 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002942
Mingming Yin497419f2015-07-01 16:57:32 -07002943 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002944 //this flag is set from framework only if its for PCM formats
2945 //no need to check for PCM format again
2946 out->non_blocking = 0;
2947 out->use_small_bufs = true;
2948 ALOGI("Keep write blocking for small buff: non_blockling %d",
2949 out->non_blocking);
2950 }
2951
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002952 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002953 out->offload_state = OFFLOAD_STATE_IDLE;
2954 out->playback_started = 0;
2955
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002956 audio_extn_dts_create_state_notifier_node(out->usecase);
2957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 create_offload_callback_thread(out);
2959 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2960 __func__, config->offload_info.version,
2961 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002962 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002963 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002964 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2965 ret = voice_check_and_set_incall_music_usecase(adev, out);
2966 if (ret != 0) {
2967 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2968 __func__, ret);
2969 goto error_open;
2970 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002971 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2972 if (config->sample_rate == 0)
2973 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2974 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2975 config->sample_rate != 8000) {
2976 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2977 ret = -EINVAL;
2978 goto error_open;
2979 }
2980 out->sample_rate = config->sample_rate;
2981 out->config.rate = config->sample_rate;
2982 if (config->format == AUDIO_FORMAT_DEFAULT)
2983 config->format = AUDIO_FORMAT_PCM_16_BIT;
2984 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2985 config->format = AUDIO_FORMAT_PCM_16_BIT;
2986 ret = -EINVAL;
2987 goto error_open;
2988 }
2989 out->format = config->format;
2990 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2991 out->config = pcm_config_afe_proxy_playback;
2992 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002993 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002994 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2996 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002998 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2999 format = AUDIO_FORMAT_PCM_16_BIT;
3000 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3001 out->config = pcm_config_deep_buffer;
3002 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003003 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003004 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003005 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003006 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003007 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003008 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 }
3010
Amit Shekhar1d896042014-10-03 13:16:09 -07003011 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3012 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003013 /* TODO remove this hardcoding and check why width is zero*/
3014 if (out->bit_width == 0)
3015 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003016 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3017 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003018 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003019 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003020 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3021 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3022 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003023 if(adev->primary_output == NULL)
3024 adev->primary_output = out;
3025 else {
3026 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003027 ret = -EEXIST;
3028 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003029 }
3030 }
3031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 /* Check if this usecase is already existing */
3033 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003034 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3035 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003038 ret = -EEXIST;
3039 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 }
3041 pthread_mutex_unlock(&adev->lock);
3042
3043 out->stream.common.get_sample_rate = out_get_sample_rate;
3044 out->stream.common.set_sample_rate = out_set_sample_rate;
3045 out->stream.common.get_buffer_size = out_get_buffer_size;
3046 out->stream.common.get_channels = out_get_channels;
3047 out->stream.common.get_format = out_get_format;
3048 out->stream.common.set_format = out_set_format;
3049 out->stream.common.standby = out_standby;
3050 out->stream.common.dump = out_dump;
3051 out->stream.common.set_parameters = out_set_parameters;
3052 out->stream.common.get_parameters = out_get_parameters;
3053 out->stream.common.add_audio_effect = out_add_audio_effect;
3054 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3055 out->stream.get_latency = out_get_latency;
3056 out->stream.set_volume = out_set_volume;
3057 out->stream.write = out_write;
3058 out->stream.get_render_position = out_get_render_position;
3059 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003060 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003063 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003064 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065
3066 config->format = out->stream.common.get_format(&out->stream.common);
3067 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3068 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3069
3070 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303071 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3072 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003073
3074 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3075 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3076 popcount(out->channel_mask), out->playback_started);
3077
Eric Laurent994a6932013-07-17 11:51:42 -07003078 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003080
3081error_open:
3082 free(out);
3083 *stream_out = NULL;
3084 ALOGD("%s: exit: ret %d", __func__, ret);
3085 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086}
3087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003088static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 struct audio_stream_out *stream)
3090{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 struct stream_out *out = (struct stream_out *)stream;
3092 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003093 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303095 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3096
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003097 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303098 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003099 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303100 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003101 if(ret != 0)
3102 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3103 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003104 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003105 out_standby(&stream->common);
3106
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003107 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003108 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003110 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 if (out->compr_config.codec != NULL)
3112 free(out->compr_config.codec);
3113 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003114
3115 if (adev->voice_tx_output == out)
3116 adev->voice_tx_output = NULL;
3117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 pthread_cond_destroy(&out->cond);
3119 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003121 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122}
3123
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003124static void close_compress_sessions(struct audio_device *adev)
3125{
Mingming Yin7b762e72015-03-04 13:47:32 -08003126 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303127 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003128 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003129 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303130
3131 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003132 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303133 if (is_offload_usecase(usecase->id)) {
3134 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003135 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3136 out = usecase->stream.out;
3137 pthread_mutex_unlock(&adev->lock);
3138 out_standby(&out->stream.common);
3139 pthread_mutex_lock(&adev->lock);
3140 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303141 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003142 }
3143 pthread_mutex_unlock(&adev->lock);
3144}
3145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3147{
3148 struct audio_device *adev = (struct audio_device *)dev;
3149 struct str_parms *parms;
3150 char *str;
3151 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003152 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 int ret;
3154 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003156 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303159 if (!parms)
3160 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003161 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3162 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303164 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303165 struct listnode *node;
3166 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303167 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303168 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003169 //close compress sessions on OFFLINE status
3170 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 } else if (strstr(snd_card_status, "ONLINE")) {
3172 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303173 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003174 //send dts hpx license if enabled
3175 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303176 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303177 }
3178
3179 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 status = voice_set_parameters(adev, parms);
3181 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003182 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003184 status = platform_set_parameters(adev->platform, parms);
3185 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003186 goto done;
3187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003188 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3189 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003190 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3192 adev->bluetooth_nrec = true;
3193 else
3194 adev->bluetooth_nrec = false;
3195 }
3196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3198 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3200 adev->screen_off = false;
3201 else
3202 adev->screen_off = true;
3203 }
3204
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003205 ret = str_parms_get_int(parms, "rotation", &val);
3206 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003207 bool reverse_speakers = false;
3208 switch(val) {
3209 // FIXME: note that the code below assumes that the speakers are in the correct placement
3210 // relative to the user when the device is rotated 90deg from its default rotation. This
3211 // assumption is device-specific, not platform-specific like this code.
3212 case 270:
3213 reverse_speakers = true;
3214 break;
3215 case 0:
3216 case 90:
3217 case 180:
3218 break;
3219 default:
3220 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003221 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003222 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003223 if (status == 0) {
3224 if (adev->speaker_lr_swap != reverse_speakers) {
3225 adev->speaker_lr_swap = reverse_speakers;
3226 // only update the selected device if there is active pcm playback
3227 struct audio_usecase *usecase;
3228 struct listnode *node;
3229 list_for_each(node, &adev->usecase_list) {
3230 usecase = node_to_item(node, struct audio_usecase, list);
3231 if (usecase->type == PCM_PLAYBACK) {
3232 select_devices(adev, usecase->id);
3233 break;
3234 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003235 }
3236 }
3237 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003238 }
3239
Mingming Yin514a8bc2014-07-29 15:22:21 -07003240 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3241 if (ret >= 0) {
3242 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3243 adev->bt_wb_speech_enabled = true;
3244 else
3245 adev->bt_wb_speech_enabled = false;
3246 }
3247
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3249 if (ret >= 0) {
3250 val = atoi(value);
3251 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3252 ALOGV("cache new edid");
3253 platform_cache_edid(adev->platform);
3254 }
3255 }
3256
3257 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3258 if (ret >= 0) {
3259 val = atoi(value);
3260 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3261 ALOGV("invalidate cached edid");
3262 platform_invalidate_edid(adev->platform);
3263 }
3264 }
3265
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003266 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003267
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003268done:
3269 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003270 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303271error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003272 ALOGV("%s: exit with code(%d)", __func__, status);
3273 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274}
3275
3276static char* adev_get_parameters(const struct audio_hw_device *dev,
3277 const char *keys)
3278{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003279 struct audio_device *adev = (struct audio_device *)dev;
3280 struct str_parms *reply = str_parms_create();
3281 struct str_parms *query = str_parms_create_str(keys);
3282 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303283 char value[256] = {0};
3284 int ret = 0;
3285
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003286 if (!query || !reply) {
3287 ALOGE("adev_get_parameters: failed to create query or reply");
3288 return NULL;
3289 }
3290
Naresh Tannirud7205b62014-06-20 02:54:48 +05303291 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3292 sizeof(value));
3293 if (ret >=0) {
3294 int val = 1;
3295 pthread_mutex_lock(&adev->snd_card_status.lock);
3296 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3297 val = 0;
3298 pthread_mutex_unlock(&adev->snd_card_status.lock);
3299 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3300 goto exit;
3301 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003302
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003303 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003304 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003305 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003306 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303307 pthread_mutex_unlock(&adev->lock);
3308
Naresh Tannirud7205b62014-06-20 02:54:48 +05303309exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003310 str = str_parms_to_str(reply);
3311 str_parms_destroy(query);
3312 str_parms_destroy(reply);
3313
3314 ALOGV("%s: exit: returns - %s", __func__, str);
3315 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316}
3317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003318static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319{
3320 return 0;
3321}
3322
3323static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3324{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003325 int ret;
3326 struct audio_device *adev = (struct audio_device *)dev;
3327 pthread_mutex_lock(&adev->lock);
3328 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003329 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003330 pthread_mutex_unlock(&adev->lock);
3331 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332}
3333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003334static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3335 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 return -ENOSYS;
3338}
3339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3341 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342{
3343 return -ENOSYS;
3344}
3345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003346static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3347 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348{
3349 return -ENOSYS;
3350}
3351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003352static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3353 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354{
3355 return -ENOSYS;
3356}
3357
3358static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3359{
3360 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 pthread_mutex_lock(&adev->lock);
3363 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003364 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003366 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3367 voice_is_in_call(adev)) {
3368 voice_stop_call(adev);
3369 adev->current_call_output = NULL;
3370 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 }
3372 pthread_mutex_unlock(&adev->lock);
3373 return 0;
3374}
3375
3376static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3377{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003378 int ret;
3379
3380 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003381 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003382 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3383 pthread_mutex_unlock(&adev->lock);
3384
3385 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386}
3387
3388static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3389{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003390 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 return 0;
3392}
3393
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003394static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 const struct audio_config *config)
3396{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003397 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003399 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3400 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401}
3402
3403static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003404 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 audio_devices_t devices,
3406 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003407 struct audio_stream_in **stream_in,
3408 audio_input_flags_t flags __unused,
3409 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003410 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411{
3412 struct audio_device *adev = (struct audio_device *)dev;
3413 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003414 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003415 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003416 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 *stream_in = NULL;
3419 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3420 return -EINVAL;
3421
3422 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003423
3424 if (!in) {
3425 ALOGE("failed to allocate input stream");
3426 return -ENOMEM;
3427 }
3428
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303429 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003430 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3431 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003433 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 in->stream.common.get_sample_rate = in_get_sample_rate;
3436 in->stream.common.set_sample_rate = in_set_sample_rate;
3437 in->stream.common.get_buffer_size = in_get_buffer_size;
3438 in->stream.common.get_channels = in_get_channels;
3439 in->stream.common.get_format = in_get_format;
3440 in->stream.common.set_format = in_set_format;
3441 in->stream.common.standby = in_standby;
3442 in->stream.common.dump = in_dump;
3443 in->stream.common.set_parameters = in_set_parameters;
3444 in->stream.common.get_parameters = in_get_parameters;
3445 in->stream.common.add_audio_effect = in_add_audio_effect;
3446 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3447 in->stream.set_gain = in_set_gain;
3448 in->stream.read = in_read;
3449 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3450
3451 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003452 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 in->standby = 1;
3455 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003456 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457
3458 /* Update config params with the requested sample rate and channels */
3459 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003460 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3461 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3462 is_low_latency = true;
3463#if LOW_LATENCY_CAPTURE_USE_CASE
3464 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3465#endif
3466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003469 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003471 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303472 if (adev->mode != AUDIO_MODE_IN_CALL) {
3473 ret = -EINVAL;
3474 goto err_open;
3475 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003476 if (config->sample_rate == 0)
3477 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3478 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3479 config->sample_rate != 8000) {
3480 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
3484 if (config->format == AUDIO_FORMAT_DEFAULT)
3485 config->format = AUDIO_FORMAT_PCM_16_BIT;
3486 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3487 config->format = AUDIO_FORMAT_PCM_16_BIT;
3488 ret = -EINVAL;
3489 goto err_open;
3490 }
3491
3492 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3493 in->config = pcm_config_afe_proxy_record;
3494 in->config.channels = channel_count;
3495 in->config.rate = config->sample_rate;
3496 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003497 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003498 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003499 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3500 ret = -EINVAL;
3501 goto err_open;
3502 }
3503 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003504 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003505 }
Mingming Yine62d7842013-10-25 16:26:03 -07003506 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003507 audio_extn_compr_cap_format_supported(config->format) &&
3508 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003509 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003510 } else {
3511 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003512 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003513 buffer_size = get_input_buffer_size(config->sample_rate,
3514 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003515 channel_count,
3516 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003517 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003518 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3519 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3520 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3521 (in->config.rate == 8000 || in->config.rate == 16000) &&
3522 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3523 voice_extn_compress_voip_open_input_stream(in);
3524 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003527 /* This stream could be for sound trigger lab,
3528 get sound trigger pcm if present */
3529 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303530 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003533 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003534 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535
3536err_open:
3537 free(in);
3538 *stream_in = NULL;
3539 return ret;
3540}
3541
3542static void adev_close_input_stream(struct audio_hw_device *dev,
3543 struct audio_stream_in *stream)
3544{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003545 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003546 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003547 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303548
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303549 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003550
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303551 /* Disable echo reference while closing input stream */
3552 platform_set_echo_reference(adev->platform, false);
3553
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003554 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303555 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003556 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303557 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003558 if (ret != 0)
3559 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3560 __func__, ret);
3561 } else
3562 in_standby(&stream->common);
3563
Mingming Yin7b762e72015-03-04 13:47:32 -08003564 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003565 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003566 audio_extn_ssr_deinit();
3567 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568
Mingming Yine62d7842013-10-25 16:26:03 -07003569 if(audio_extn_compr_cap_enabled() &&
3570 audio_extn_compr_cap_format_supported(in->config.format))
3571 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003572
3573 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 return;
3575}
3576
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003577static int adev_dump(const audio_hw_device_t *device __unused,
3578 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579{
3580 return 0;
3581}
3582
3583static int adev_close(hw_device_t *device)
3584{
3585 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003586
3587 if (!adev)
3588 return 0;
3589
3590 pthread_mutex_lock(&adev_init_lock);
3591
3592 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003593 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003594 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003595 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003596 audio_route_free(adev->audio_route);
3597 free(adev->snd_dev_ref_cnt);
3598 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003599 free(device);
3600 adev = NULL;
3601 }
3602 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 return 0;
3604}
3605
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003606/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3607 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3608 * just that it _might_ work.
3609 */
3610static int period_size_is_plausible_for_low_latency(int period_size)
3611{
3612 switch (period_size) {
3613 case 160:
3614 case 240:
3615 case 320:
3616 case 480:
3617 return 1;
3618 default:
3619 return 0;
3620 }
3621}
3622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623static int adev_open(const hw_module_t *module, const char *name,
3624 hw_device_t **device)
3625{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003626 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003628 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3630
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003631 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003632 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003633 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003634 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003635 ALOGD("%s: returning existing instance of adev", __func__);
3636 ALOGD("%s: exit", __func__);
3637 pthread_mutex_unlock(&adev_init_lock);
3638 return 0;
3639 }
3640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 adev = calloc(1, sizeof(struct audio_device));
3642
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003643 if (!adev) {
3644 pthread_mutex_unlock(&adev_init_lock);
3645 return -ENOMEM;
3646 }
3647
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003648 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3651 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3652 adev->device.common.module = (struct hw_module_t *)module;
3653 adev->device.common.close = adev_close;
3654
3655 adev->device.init_check = adev_init_check;
3656 adev->device.set_voice_volume = adev_set_voice_volume;
3657 adev->device.set_master_volume = adev_set_master_volume;
3658 adev->device.get_master_volume = adev_get_master_volume;
3659 adev->device.set_master_mute = adev_set_master_mute;
3660 adev->device.get_master_mute = adev_get_master_mute;
3661 adev->device.set_mode = adev_set_mode;
3662 adev->device.set_mic_mute = adev_set_mic_mute;
3663 adev->device.get_mic_mute = adev_get_mic_mute;
3664 adev->device.set_parameters = adev_set_parameters;
3665 adev->device.get_parameters = adev_get_parameters;
3666 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3667 adev->device.open_output_stream = adev_open_output_stream;
3668 adev->device.close_output_stream = adev_close_output_stream;
3669 adev->device.open_input_stream = adev_open_input_stream;
3670 adev->device.close_input_stream = adev_close_input_stream;
3671 adev->device.dump = adev_dump;
3672
3673 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003675 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003676 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003679 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003680 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003681 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003682 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003683 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003684 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003685 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303686
3687 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3688 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003690 adev->platform = platform_init(adev);
3691 if (!adev->platform) {
3692 free(adev->snd_dev_ref_cnt);
3693 free(adev);
3694 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3695 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003696 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003697 return -EINVAL;
3698 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003699
Naresh Tanniru4c630392014-05-12 01:05:52 +05303700 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3701
Eric Laurentc4aef752013-09-12 17:45:53 -07003702 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3703 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3704 if (adev->visualizer_lib == NULL) {
3705 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3706 } else {
3707 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3708 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003709 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003710 "visualizer_hal_start_output");
3711 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003712 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003713 "visualizer_hal_stop_output");
3714 }
3715 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003716 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003717 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003718
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003719 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3720 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3721 if (adev->offload_effects_lib == NULL) {
3722 ALOGE("%s: DLOPEN failed for %s", __func__,
3723 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3724 } else {
3725 ALOGV("%s: DLOPEN successful for %s", __func__,
3726 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3727 adev->offload_effects_start_output =
3728 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3729 "offload_effects_bundle_hal_start_output");
3730 adev->offload_effects_stop_output =
3731 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3732 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003733 adev->offload_effects_set_hpx_state =
3734 (int (*)(bool))dlsym(adev->offload_effects_lib,
3735 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003736 }
3737 }
3738
Mingming Yin514a8bc2014-07-29 15:22:21 -07003739 adev->bt_wb_speech_enabled = false;
3740
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003741 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 *device = &adev->device.common;
3743
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003744 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3745 &adev->streams_output_cfg_list);
3746
Kiran Kandi910e1862013-10-29 13:29:42 -07003747 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003748
3749 char value[PROPERTY_VALUE_MAX];
3750 int trial;
3751 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3752 trial = atoi(value);
3753 if (period_size_is_plausible_for_low_latency(trial)) {
3754 pcm_config_low_latency.period_size = trial;
3755 pcm_config_low_latency.start_threshold = trial / 4;
3756 pcm_config_low_latency.avail_min = trial / 4;
3757 configured_low_latency_capture_period_size = trial;
3758 }
3759 }
3760 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3761 trial = atoi(value);
3762 if (period_size_is_plausible_for_low_latency(trial)) {
3763 configured_low_latency_capture_period_size = trial;
3764 }
3765 }
3766
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003767 pthread_mutex_unlock(&adev_init_lock);
3768
Eric Laurent994a6932013-07-17 11:51:42 -07003769 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 return 0;
3771}
3772
3773static struct hw_module_methods_t hal_module_methods = {
3774 .open = adev_open,
3775};
3776
3777struct audio_module HAL_MODULE_INFO_SYM = {
3778 .common = {
3779 .tag = HARDWARE_MODULE_TAG,
3780 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3781 .hal_api_version = HARDWARE_HAL_API_VERSION,
3782 .id = AUDIO_HARDWARE_MODULE_ID,
3783 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003784 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 .methods = &hal_module_methods,
3786 },
3787};