blob: 1dadf0f01213ddca895700c5176d2876d66874b3 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
vivek mehtaa76401a2015-04-24 14:12:15 -0700255__attribute__ ((visibility ("default")))
256bool audio_hw_send_gain_dep_calibration(int level) {
257 bool ret_val = false;
258 ALOGV("%s: called ... ", __func__);
259
260 pthread_mutex_lock(&adev_init_lock);
261
262 if (adev != NULL && adev->platform != NULL) {
263 pthread_mutex_lock(&adev->lock);
264 ret_val = platform_send_gain_dep_cal(adev->platform, level);
265 pthread_mutex_unlock(&adev->lock);
266 } else {
267 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
268 }
269
270 pthread_mutex_unlock(&adev_init_lock);
271
272 return ret_val;
273}
274
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800275static int check_and_set_gapless_mode(struct audio_device *adev) {
276
277
278 char value[PROPERTY_VALUE_MAX] = {0};
279 bool gapless_enabled = false;
280 const char *mixer_ctl_name = "Compress Gapless Playback";
281 struct mixer_ctl *ctl;
282
283 ALOGV("%s:", __func__);
284 property_get("audio.offload.gapless.enabled", value, NULL);
285 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
286
287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
288 if (!ctl) {
289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
290 __func__, mixer_ctl_name);
291 return -EINVAL;
292 }
293
294 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
295 ALOGE("%s: Could not set gapless mode %d",
296 __func__, gapless_enabled);
297 return -EINVAL;
298 }
299 return 0;
300}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700302static bool is_supported_format(audio_format_t format)
303{
Eric Laurent86e17132013-09-12 17:49:30 -0700304 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 format == AUDIO_FORMAT_AAC_LC ||
306 format == AUDIO_FORMAT_AAC_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800310 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530311 format == AUDIO_FORMAT_ALAC ||
312 format == AUDIO_FORMAT_APE ||
313 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_WMA ||
315 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800316 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317
318 return false;
319}
320
321static int get_snd_codec_id(audio_format_t format)
322{
323 int id = 0;
324
Ashish Jainf9b78162014-08-25 20:36:25 +0530325 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700326 case AUDIO_FORMAT_MP3:
327 id = SND_AUDIOCODEC_MP3;
328 break;
329 case AUDIO_FORMAT_AAC:
330 id = SND_AUDIOCODEC_AAC;
331 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800333 id = SND_AUDIOCODEC_PCM;
334 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700335 case AUDIO_FORMAT_FLAC:
336 id = SND_AUDIOCODEC_FLAC;
337 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530338 case AUDIO_FORMAT_ALAC:
339 id = SND_AUDIOCODEC_ALAC;
340 break;
341 case AUDIO_FORMAT_APE:
342 id = SND_AUDIOCODEC_APE;
343 break;
344 case AUDIO_FORMAT_VORBIS:
345 id = SND_AUDIOCODEC_VORBIS;
346 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800347 case AUDIO_FORMAT_WMA:
348 id = SND_AUDIOCODEC_WMA;
349 break;
350 case AUDIO_FORMAT_WMA_PRO:
351 id = SND_AUDIOCODEC_WMA_PRO;
352 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700353 default:
Mingming Yin90310102013-11-13 16:57:00 -0800354 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700355 }
356
357 return id;
358}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800359
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530360int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530361{
362 int snd_scard_state;
363
364 if (!adev)
365 return SND_CARD_STATE_OFFLINE;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 snd_scard_state = adev->snd_card_status.state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return snd_scard_state;
372}
373
374static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
375{
376 if (!adev)
377 return -ENOSYS;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700380 if (adev->snd_card_status.state != snd_scard_state) {
381 adev->snd_card_status.state = snd_scard_state;
382 platform_snd_card_update(adev->platform, snd_scard_state);
383 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530384 pthread_mutex_unlock(&adev->snd_card_status.lock);
385
386 return 0;
387}
388
Avinash Vaish71a8b972014-07-24 15:36:33 +0530389static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
390 struct audio_usecase *uc_info)
391{
392 struct listnode *node;
393 struct audio_usecase *usecase;
394
395 if (uc_info == NULL)
396 return -EINVAL;
397
398 /* Re-route all voice usecases on the shared backend other than the
399 specified usecase to new snd devices */
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800402 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530403 enable_audio_route(adev, usecase);
404 }
405 return 0;
406}
407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700408int pcm_ioctl(struct pcm *pcm, int request, ...)
409{
410 va_list ap;
411 void * arg;
412 int pcm_fd = *(int*)pcm;
413
414 va_start(ap, request);
415 arg = va_arg(ap, void *);
416 va_end(ap);
417
418 return ioctl(pcm_fd, request, arg);
419}
420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700421int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700422 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700425 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426
427 if (usecase == NULL)
428 return -EINVAL;
429
430 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
431
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800434 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800437#ifdef DS1_DOLBY_DAP_ENABLED
438 audio_extn_dolby_set_dmid(adev);
439 audio_extn_dolby_set_endpoint(adev);
440#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700441 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530443 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700444 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700445 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700448 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
449 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 ALOGV("%s: exit", __func__);
451 return 0;
452}
453
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700454int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700455 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530460 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461 return -EINVAL;
462
463 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 if (usecase->type == PCM_CAPTURE)
465 snd_device = usecase->in_snd_device;
466 else
467 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700469 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700470 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
471 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700472 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530473 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700478int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800483 if (snd_device < SND_DEVICE_MIN ||
484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800486 return -EINVAL;
487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
489 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490
491 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
492 ALOGE("%s: Invalid sound device returned", __func__);
493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700496 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 return 0;
499 }
500
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700501 if (audio_extn_spkr_prot_is_enabled())
502 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 /* start usb playback thread */
504 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
505 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
506 audio_extn_usb_start_playback(adev);
507
508 /* start usb capture thread */
509 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
510 audio_extn_usb_start_capture(adev);
511
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800512 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
513 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700514 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700515 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
516 adev->snd_dev_ref_cnt[snd_device]--;
517 return -EINVAL;
518 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200519 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800520 if (audio_extn_spkr_prot_start_processing(snd_device)) {
521 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200522 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 return -EINVAL;
524 }
525 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
527 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700528 /* due to the possibility of calibration overwrite between listen
529 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700530 audio_extn_sound_trigger_update_device_status(snd_device,
531 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530532 audio_extn_listen_update_device_status(snd_device,
533 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700534 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700535 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 return -EINVAL;
541 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300542 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700543 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 return 0;
546}
547
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700548int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700549 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800553 if (snd_device < SND_DEVICE_MIN ||
554 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800555 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 return -EINVAL;
557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
559 ALOGE("%s: device ref cnt is already 0", __func__);
560 return -EINVAL;
561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700571 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800573 /* exit usb play back thread */
574 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
575 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
576 audio_extn_usb_stop_playback();
577
578 /* exit usb capture thread */
579 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700580 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800581
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
583 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700584 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700585 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700589
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200590 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700591 audio_extn_sound_trigger_update_device_status(snd_device,
592 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530593 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800594 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 return 0;
598}
599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600static void check_usecases_codec_backend(struct audio_device *adev,
601 struct audio_usecase *uc_info,
602 snd_device_t snd_device)
603{
604 struct listnode *node;
605 struct audio_usecase *usecase;
606 bool switch_device[AUDIO_USECASE_MAX];
607 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800608 int backend_idx = DEFAULT_CODEC_BACKEND;
609 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
611 /*
612 * This function is to make sure that all the usecases that are active on
613 * the hardware codec backend are always routed to any one device that is
614 * handled by the hardware codec.
615 * For example, if low-latency and deep-buffer usecases are currently active
616 * on speaker and out_set_parameters(headset) is received on low-latency
617 * output, then we have to make sure deep-buffer is also switched to headset,
618 * because of the limitation that both the devices cannot be enabled
619 * at the same time as they share the same backend.
620 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700621 /*
622 * This call is to check if we need to force routing for a particular stream
623 * If there is a backend configuration change for the device when a
624 * new stream starts, then ADM needs to be closed and re-opened with the new
625 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800626 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800628 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
629 snd_device);
630 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800632 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800633 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 for (i = 0; i < AUDIO_USECASE_MAX; i++)
635 switch_device[i] = false;
636
637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639
640 if (usecase == uc_info)
641 continue;
642 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
643 ALOGV("%s: backend_idx: %d,"
644 "usecase_backend_idx: %d, curr device: %s, usecase device:"
645 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530646 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800647
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800648 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700649 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
651 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530652 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700654 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700655 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 switch_device[usecase->id] = true;
657 num_uc_to_switch++;
658 }
659 }
660
661 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700662 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530664 /* Make sure the previous devices to be disabled first and then enable the
665 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
668 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
675 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700677 }
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 /* Re-route all the usecases on the shared backend other than the
681 specified usecase to new snd devices */
682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530684 /* Update the out_snd_device only for the usecases that are enabled here */
685 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
686 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530687 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 }
689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690 }
691}
692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693static void check_and_route_capture_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info,
695 snd_device_t snd_device)
696{
697 struct listnode *node;
698 struct audio_usecase *usecase;
699 bool switch_device[AUDIO_USECASE_MAX];
700 int i, num_uc_to_switch = 0;
701
702 /*
703 * This function is to make sure that all the active capture usecases
704 * are always routed to the same input sound device.
705 * For example, if audio-record and voice-call usecases are currently
706 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
707 * is received for voice call then we have to make sure that audio-record
708 * usecase is also switched to earpiece i.e. voice-dmic-ef,
709 * because of the limitation that two devices cannot be enabled
710 * at the same time if they share the same backend.
711 */
712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
713 switch_device[i] = false;
714
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700719 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700720 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
721 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700722 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700723 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
724 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700725 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 switch_device[usecase->id] = true;
728 num_uc_to_switch++;
729 }
730 }
731
732 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700733 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530735 /* Make sure the previous devices to be disabled first and then enable the
736 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800741 }
742 }
743
744 list_for_each(node, &adev->usecase_list) {
745 usecase = node_to_item(node, struct audio_usecase, list);
746 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 }
749 }
750
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 /* Re-route all the usecases on the shared backend other than the
752 specified usecase to new snd devices */
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 /* Update the in_snd_device only before enabling the audio route */
756 if (switch_device[usecase->id] ) {
757 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800758 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530759 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763}
764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700766static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700768 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700769 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770
771 switch (channels) {
772 /*
773 * Do not handle stereo output in Multi-channel cases
774 * Stereo case is handled in normal playback path
775 */
776 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 break;
784 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700785 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700794 ALOGE("HDMI does not support multi channel playback");
795 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796 break;
797 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700798 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799}
800
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800801audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
802 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800809 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700810 ALOGV("%s: usecase id %d", __func__, usecase->id);
811 return usecase->id;
812 }
813 }
814 return USECASE_INVALID;
815}
816
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700817struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
825 if (usecase->id == uc_id)
826 return usecase;
827 }
828 return NULL;
829}
830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700831int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800833 snd_device_t out_snd_device = SND_DEVICE_NONE;
834 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 struct audio_usecase *usecase = NULL;
836 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800837 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800838 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800839 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800840 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 usecase = get_usecase_from_list(adev, uc_id);
844 if (usecase == NULL) {
845 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
846 return -EINVAL;
847 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800850 (usecase->type == VOIP_CALL) ||
851 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700852 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800853 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700854 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase->devices = usecase->stream.out->devices;
856 } else {
857 /*
858 * If the voice call is active, use the sound devices of voice call usecase
859 * so that it would not result any device switch. All the usecases will
860 * be switched to new device when select_devices() is called for voice call
861 * usecase. This is to avoid switching devices for voice call when
862 * check_usecases_codec_backend() is called below.
863 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700864 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700865 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800866 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
868 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 in_snd_device = vc_usecase->in_snd_device;
870 out_snd_device = vc_usecase->out_snd_device;
871 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800872 } else if (voice_extn_compress_voip_is_active(adev)) {
873 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700874 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530875 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 in_snd_device = voip_usecase->in_snd_device;
878 out_snd_device = voip_usecase->out_snd_device;
879 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800880 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800881 hfp_ucid = audio_extn_hfp_get_usecase();
882 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800884 in_snd_device = hfp_usecase->in_snd_device;
885 out_snd_device = hfp_usecase->out_snd_device;
886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 }
888 if (usecase->type == PCM_PLAYBACK) {
889 usecase->devices = usecase->stream.out->devices;
890 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700892 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800893 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700894 if (usecase->stream.out == adev->primary_output &&
895 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800896 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 select_devices(adev, adev->active_input->usecase);
898 }
899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 } else if (usecase->type == PCM_CAPTURE) {
901 usecase->devices = usecase->stream.in->device;
902 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700904 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530905 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
906 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
907 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
908 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700909 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
912 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700914 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 }
917 }
918
919 if (out_snd_device == usecase->out_snd_device &&
920 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922 }
923
sangwoobc677242013-08-08 16:53:43 +0900924 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700925 out_snd_device, platform_get_snd_device_name(out_snd_device),
926 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 /*
929 * Limitation: While in call, to do a device switch we need to disable
930 * and enable both RX and TX devices though one of them is same as current
931 * device.
932 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700933 if ((usecase->type == VOICE_CALL) &&
934 (usecase->in_snd_device != SND_DEVICE_NONE) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700937 }
938
939 if (((usecase->type == VOICE_CALL) ||
940 (usecase->type == VOIP_CALL)) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
942 /* Disable sidetone only if voice/voip call already exists */
943 if (voice_is_call_state_active(adev) ||
944 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700945 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 /* Disable current sound devices */
949 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700950 disable_audio_route(adev, usecase);
951 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700955 disable_audio_route(adev, usecase);
956 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957 }
958
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800959 /* Applicable only on the targets that has external modem.
960 * New device information should be sent to modem before enabling
961 * the devices to reduce in-call device switch time.
962 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 if ((usecase->type == VOICE_CALL) &&
964 (usecase->in_snd_device != SND_DEVICE_NONE) &&
965 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800966 status = platform_switch_voice_call_enable_device_config(adev->platform,
967 out_snd_device,
968 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700969 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Enable new sound devices */
972 if (out_snd_device != SND_DEVICE_NONE) {
973 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
974 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700975 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976 }
977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700978 if (in_snd_device != SND_DEVICE_NONE) {
979 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700981 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982
Avinash Vaish71a8b972014-07-24 15:36:33 +0530983 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700984 status = platform_switch_voice_call_device_post(adev->platform,
985 out_snd_device,
986 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530987 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700988 /* Enable sidetone only if voice/voip call already exists */
989 if (voice_is_call_state_active(adev) ||
990 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700991 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800993
sangwoo170731f2013-06-08 15:36:36 +0900994 usecase->in_snd_device = in_snd_device;
995 usecase->out_snd_device = out_snd_device;
996
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530997 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700998 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530999 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 usecase->stream.out->flags,
1002 usecase->stream.out->format,
1003 usecase->stream.out->sample_rate,
1004 usecase->stream.out->bit_width,
1005 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001006 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301007 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001008
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001009 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001010
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001011 /* Applicable only on the targets that has external modem.
1012 * Enable device command should be sent to modem only after
1013 * enabling voice call mixer controls
1014 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001015 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001016 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1017 out_snd_device,
1018 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301019 ALOGD("%s: done",__func__);
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 return status;
1022}
1023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024static int stop_input_stream(struct stream_in *in)
1025{
1026 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 struct audio_usecase *uc_info;
1028 struct audio_device *adev = in->dev;
1029
Eric Laurentc8400632013-02-14 19:04:54 -08001030 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031
Eric Laurent994a6932013-07-17 11:51:42 -07001032 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 uc_info = get_usecase_from_list(adev, in->usecase);
1035 if (uc_info == NULL) {
1036 ALOGE("%s: Could not find the usecase (%d) in the list",
1037 __func__, in->usecase);
1038 return -EINVAL;
1039 }
1040
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001041 /* Close in-call recording streams */
1042 voice_check_and_stop_incall_rec_usecase(adev, in);
1043
Eric Laurent150dbfe2013-02-27 14:31:02 -08001044 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001045 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046
1047 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001048 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001050 list_remove(&uc_info->list);
1051 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052
Eric Laurent994a6932013-07-17 11:51:42 -07001053 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 return ret;
1055}
1056
1057int start_input_stream(struct stream_in *in)
1058{
1059 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 struct audio_usecase *uc_info;
1062 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301063 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Mingming Yine62d7842013-10-25 16:26:03 -07001065 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301066 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1067 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001068
Naresh Tanniru80659832014-06-04 18:17:56 +05301069
1070 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301071 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301072 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301073 goto error_config;
1074 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301075
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001076 /* Check if source matches incall recording usecase criteria */
1077 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1078 if (ret)
1079 goto error_config;
1080 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001081 ALOGD("%s: Updated usecase(%d: %s)",
1082 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001083
Eric Laurentb23d5282013-05-14 15:27:20 -07001084 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 if (in->pcm_device_id < 0) {
1086 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1087 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001088 ret = -EINVAL;
1089 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091
1092 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001094
1095 if (!uc_info) {
1096 ret = -ENOMEM;
1097 goto error_config;
1098 }
1099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 uc_info->id = in->usecase;
1101 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001102 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 uc_info->devices = in->device;
1104 uc_info->in_snd_device = SND_DEVICE_NONE;
1105 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001107 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301108 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110
Eric Laurentc8400632013-02-14 19:04:54 -08001111 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001112 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1113
1114 unsigned int flags = PCM_IN;
1115 unsigned int pcm_open_retry_count = 0;
1116
1117 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1118 flags |= PCM_MMAP | PCM_NOIRQ;
1119 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1120 }
1121
1122 while (1) {
1123 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1124 flags, &in->config);
1125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1126 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1127 if (in->pcm != NULL) {
1128 pcm_close(in->pcm);
1129 in->pcm = NULL;
1130 }
1131 if (pcm_open_retry_count-- == 0) {
1132 ret = -EIO;
1133 goto error_open;
1134 }
1135 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1136 continue;
1137 }
1138 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301140 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301141
Eric Laurent994a6932013-07-17 11:51:42 -07001142 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001143 return ret;
1144
1145error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301147 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001148
1149error_config:
1150 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001152
1153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154}
1155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001156/* must be called with out->lock locked */
1157static int send_offload_cmd_l(struct stream_out* out, int command)
1158{
1159 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1160
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001161 if (!cmd) {
1162 ALOGE("failed to allocate mem for command 0x%x", command);
1163 return -ENOMEM;
1164 }
1165
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001166 ALOGVV("%s %d", __func__, command);
1167
1168 cmd->cmd = command;
1169 list_add_tail(&out->offload_cmd_list, &cmd->node);
1170 pthread_cond_signal(&out->offload_cond);
1171 return 0;
1172}
1173
1174/* must be called iwth out->lock locked */
1175static void stop_compressed_output_l(struct stream_out *out)
1176{
1177 out->offload_state = OFFLOAD_STATE_IDLE;
1178 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001179 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001180 if (out->compr != NULL) {
1181 compress_stop(out->compr);
1182 while (out->offload_thread_blocked) {
1183 pthread_cond_wait(&out->cond, &out->lock);
1184 }
1185 }
1186}
1187
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001188bool is_offload_usecase(audio_usecase_t uc_id)
1189{
1190 unsigned int i;
1191 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1192 if (uc_id == offload_usecases[i])
1193 return true;
1194 }
1195 return false;
1196}
1197
1198static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1199{
1200 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1201 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1202 char value[PROPERTY_VALUE_MAX] = {0};
1203
1204 property_get("audio.offload.multiple.enabled", value, NULL);
1205 if (!(atoi(value) || !strncmp("true", value, 4)))
1206 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1207
1208 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1209 for (i = 0; i < num_usecase; i++) {
1210 if (!(adev->offload_usecases_state & (0x1<<i))) {
1211 adev->offload_usecases_state |= 0x1 << i;
1212 ret = offload_usecases[i];
1213 break;
1214 }
1215 }
1216 ALOGV("%s: offload usecase is %d", __func__, ret);
1217 return ret;
1218}
1219
1220static void free_offload_usecase(struct audio_device *adev,
1221 audio_usecase_t uc_id)
1222{
1223 unsigned int i;
1224 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1225 if (offload_usecases[i] == uc_id) {
1226 adev->offload_usecases_state &= ~(0x1<<i);
1227 break;
1228 }
1229 }
1230 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1231}
1232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233static void *offload_thread_loop(void *context)
1234{
1235 struct stream_out *out = (struct stream_out *) context;
1236 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001237 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1240 set_sched_policy(0, SP_FOREGROUND);
1241 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1242
1243 ALOGV("%s", __func__);
1244 pthread_mutex_lock(&out->lock);
1245 for (;;) {
1246 struct offload_cmd *cmd = NULL;
1247 stream_callback_event_t event;
1248 bool send_callback = false;
1249
1250 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1251 __func__, list_empty(&out->offload_cmd_list),
1252 out->offload_state);
1253 if (list_empty(&out->offload_cmd_list)) {
1254 ALOGV("%s SLEEPING", __func__);
1255 pthread_cond_wait(&out->offload_cond, &out->lock);
1256 ALOGV("%s RUNNING", __func__);
1257 continue;
1258 }
1259
1260 item = list_head(&out->offload_cmd_list);
1261 cmd = node_to_item(item, struct offload_cmd, node);
1262 list_remove(item);
1263
1264 ALOGVV("%s STATE %d CMD %d out->compr %p",
1265 __func__, out->offload_state, cmd->cmd, out->compr);
1266
1267 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1268 free(cmd);
1269 break;
1270 }
1271
1272 if (out->compr == NULL) {
1273 ALOGE("%s: Compress handle is NULL", __func__);
1274 pthread_cond_signal(&out->cond);
1275 continue;
1276 }
1277 out->offload_thread_blocked = true;
1278 pthread_mutex_unlock(&out->lock);
1279 send_callback = false;
1280 switch(cmd->cmd) {
1281 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001282 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001283 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001284 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001285 send_callback = true;
1286 event = STREAM_CBK_EVENT_WRITE_READY;
1287 break;
1288 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001289 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301290 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301292 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001293 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301294 if (ret < 0)
1295 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301296 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301297 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001298 compress_drain(out->compr);
1299 else
1300 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301301 if (ret != -ENETRESET) {
1302 send_callback = true;
1303 event = STREAM_CBK_EVENT_DRAIN_READY;
1304 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1305 } else
1306 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 break;
1308 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001309 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001311 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 send_callback = true;
1313 event = STREAM_CBK_EVENT_DRAIN_READY;
1314 break;
1315 default:
1316 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1317 break;
1318 }
1319 pthread_mutex_lock(&out->lock);
1320 out->offload_thread_blocked = false;
1321 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001322 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001323 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001325 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001326 free(cmd);
1327 }
1328
1329 pthread_cond_signal(&out->cond);
1330 while (!list_empty(&out->offload_cmd_list)) {
1331 item = list_head(&out->offload_cmd_list);
1332 list_remove(item);
1333 free(node_to_item(item, struct offload_cmd, node));
1334 }
1335 pthread_mutex_unlock(&out->lock);
1336
1337 return NULL;
1338}
1339
1340static int create_offload_callback_thread(struct stream_out *out)
1341{
1342 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1343 list_init(&out->offload_cmd_list);
1344 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1345 offload_thread_loop, out);
1346 return 0;
1347}
1348
1349static int destroy_offload_callback_thread(struct stream_out *out)
1350{
1351 pthread_mutex_lock(&out->lock);
1352 stop_compressed_output_l(out);
1353 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1354
1355 pthread_mutex_unlock(&out->lock);
1356 pthread_join(out->offload_thread, (void **) NULL);
1357 pthread_cond_destroy(&out->offload_cond);
1358
1359 return 0;
1360}
1361
Eric Laurent07eeafd2013-10-06 12:52:49 -07001362static bool allow_hdmi_channel_config(struct audio_device *adev)
1363{
1364 struct listnode *node;
1365 struct audio_usecase *usecase;
1366 bool ret = true;
1367
1368 list_for_each(node, &adev->usecase_list) {
1369 usecase = node_to_item(node, struct audio_usecase, list);
1370 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1371 /*
1372 * If voice call is already existing, do not proceed further to avoid
1373 * disabling/enabling both RX and TX devices, CSD calls, etc.
1374 * Once the voice call done, the HDMI channels can be configured to
1375 * max channels of remaining use cases.
1376 */
1377 if (usecase->id == USECASE_VOICE_CALL) {
1378 ALOGD("%s: voice call is active, no change in HDMI channels",
1379 __func__);
1380 ret = false;
1381 break;
1382 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1383 ALOGD("%s: multi channel playback is active, "
1384 "no change in HDMI channels", __func__);
1385 ret = false;
1386 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001387 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001388 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001389 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1390 ", no change in HDMI channels", __func__,
1391 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001392 ret = false;
1393 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 }
1395 }
1396 }
1397 return ret;
1398}
1399
1400static int check_and_set_hdmi_channels(struct audio_device *adev,
1401 unsigned int channels)
1402{
1403 struct listnode *node;
1404 struct audio_usecase *usecase;
1405
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001406 unsigned int supported_channels = platform_edid_get_max_channels(
1407 adev->platform);
1408 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001409 /* Check if change in HDMI channel config is allowed */
1410 if (!allow_hdmi_channel_config(adev))
1411 return 0;
1412
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001413 if (channels > supported_channels)
1414 channels = supported_channels;
1415
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001417 ALOGD("%s: Requested channels are same as current channels(%d)",
1418 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 return 0;
1420 }
1421
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001422 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001424 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425 adev->cur_hdmi_channels = channels;
1426
1427 /*
1428 * Deroute all the playback streams routed to HDMI so that
1429 * the back end is deactivated. Note that backend will not
1430 * be deactivated if any one stream is connected to it.
1431 */
1432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
1434 if (usecase->type == PCM_PLAYBACK &&
1435 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001436 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001437 }
1438 }
1439
1440 /*
1441 * Enable all the streams disabled above. Now the HDMI backend
1442 * will be activated with new channel configuration
1443 */
1444 list_for_each(node, &adev->usecase_list) {
1445 usecase = node_to_item(node, struct audio_usecase, list);
1446 if (usecase->type == PCM_PLAYBACK &&
1447 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 }
1450 }
1451
1452 return 0;
1453}
1454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455static int stop_output_stream(struct stream_out *out)
1456{
1457 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 struct audio_usecase *uc_info;
1459 struct audio_device *adev = out->dev;
1460
Eric Laurent994a6932013-07-17 11:51:42 -07001461 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 uc_info = get_usecase_from_list(adev, out->usecase);
1464 if (uc_info == NULL) {
1465 ALOGE("%s: Could not find the usecase (%d) in the list",
1466 __func__, out->usecase);
1467 return -EINVAL;
1468 }
1469
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001470 if (is_offload_usecase(out->usecase) &&
1471 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001472 if (adev->visualizer_stop_output != NULL)
1473 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001474
1475 audio_extn_dts_remove_state_notifier_node(out->usecase);
1476
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001477 if (adev->offload_effects_stop_output != NULL)
1478 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1479 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001480
Eric Laurent150dbfe2013-02-27 14:31:02 -08001481 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001482 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483
1484 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001485 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001487 list_remove(&uc_info->list);
1488 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001490 if (is_offload_usecase(out->usecase) &&
1491 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1492 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1493 ALOGV("Disable passthrough , reset mixer to pcm");
1494 /* NO_PASSTHROUGH */
1495 out->compr_config.codec->compr_passthr = 0;
1496 audio_extn_dolby_set_hdmi_config(adev, out);
1497 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1498 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001499 /* Must be called after removing the usecase from list */
1500 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1501 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1502
Eric Laurent994a6932013-07-17 11:51:42 -07001503 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 return ret;
1505}
1506
1507int start_output_stream(struct stream_out *out)
1508{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001510 int sink_channels = 0;
1511 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 struct audio_usecase *uc_info;
1513 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301514 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001516 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1517 ret = -EINVAL;
1518 goto error_config;
1519 }
1520
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301521 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1522 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1523 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301524
Naresh Tanniru80659832014-06-04 18:17:56 +05301525 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301526 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301527 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301528 goto error_config;
1529 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301530
Eric Laurentb23d5282013-05-14 15:27:20 -07001531 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 if (out->pcm_device_id < 0) {
1533 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1534 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001535 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 }
1538
1539 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001540
1541 if (!uc_info) {
1542 ret = -ENOMEM;
1543 goto error_config;
1544 }
1545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 uc_info->id = out->usecase;
1547 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001548 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549 uc_info->devices = out->devices;
1550 uc_info->in_snd_device = SND_DEVICE_NONE;
1551 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001552 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001553 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001554 if (is_offload_usecase(out->usecase)) {
1555 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001556 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1557 }
1558 }
Mingming Yin9c041392014-05-01 15:37:31 -07001559 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1560 if (!strncmp("true", prop_value, 4)) {
1561 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001562 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1563 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001564 check_and_set_hdmi_channels(adev, sink_channels);
1565 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001566 if (is_offload_usecase(out->usecase)) {
1567 unsigned int ch_count = out->compr_config.codec->ch_in;
1568 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1569 /* backend channel config for passthrough stream is stereo */
1570 ch_count = 2;
1571 check_and_set_hdmi_channels(adev, ch_count);
1572 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001573 check_and_set_hdmi_channels(adev, out->config.channels);
1574 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001575 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001576 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001577 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579 select_devices(adev, out->usecase);
1580
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001581 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1582 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001583 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 unsigned int flags = PCM_OUT;
1585 unsigned int pcm_open_retry_count = 0;
1586 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1587 flags |= PCM_MMAP | PCM_NOIRQ;
1588 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1589 } else
1590 flags |= PCM_MONOTONIC;
1591
1592 while (1) {
1593 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1594 flags, &out->config);
1595 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1596 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1597 if (out->pcm != NULL) {
1598 pcm_close(out->pcm);
1599 out->pcm = NULL;
1600 }
1601 if (pcm_open_retry_count-- == 0) {
1602 ret = -EIO;
1603 goto error_open;
1604 }
1605 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1606 continue;
1607 }
1608 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001610 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1611 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001613 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1614 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001616 out->compr = compress_open(adev->snd_card,
1617 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 COMPRESS_IN, &out->compr_config);
1619 if (out->compr && !is_compress_ready(out->compr)) {
1620 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1621 compress_close(out->compr);
1622 out->compr = NULL;
1623 ret = -EIO;
1624 goto error_open;
1625 }
1626 if (out->offload_callback)
1627 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001628
Fred Oh3f43e742015-03-04 18:42:34 -08001629 /* Since small bufs uses blocking writes, a write will be blocked
1630 for the default max poll time (20s) in the event of an SSR.
1631 Reduce the poll time to observe and deal with SSR faster.
1632 */
1633 if (out->use_small_bufs) {
1634 compress_set_max_poll_wait(out->compr, 1000);
1635 }
1636
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001637 audio_extn_dts_create_state_notifier_node(out->usecase);
1638 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1639 popcount(out->channel_mask),
1640 out->playback_started);
1641
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001642#ifdef DS1_DOLBY_DDP_ENABLED
1643 if (audio_extn_is_dolby_format(out->format))
1644 audio_extn_dolby_send_ddp_endp_params(adev);
1645#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001646 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1647 if (adev->visualizer_start_output != NULL)
1648 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1649 if (adev->offload_effects_start_output != NULL)
1650 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001651 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
Eric Laurent994a6932013-07-17 11:51:42 -07001654 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001656error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001658error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001659 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660}
1661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662static int check_input_parameters(uint32_t sample_rate,
1663 audio_format_t format,
1664 int channel_count)
1665{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001666 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001668 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001669 !voice_extn_compress_voip_is_format_supported(format) &&
1670 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001671
1672 switch (channel_count) {
1673 case 1:
1674 case 2:
1675 case 6:
1676 break;
1677 default:
1678 ret = -EINVAL;
1679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680
1681 switch (sample_rate) {
1682 case 8000:
1683 case 11025:
1684 case 12000:
1685 case 16000:
1686 case 22050:
1687 case 24000:
1688 case 32000:
1689 case 44100:
1690 case 48000:
1691 break;
1692 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001693 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001696 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697}
1698
1699static size_t get_input_buffer_size(uint32_t sample_rate,
1700 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001701 int channel_count,
1702 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703{
1704 size_t size = 0;
1705
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001706 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1707 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001709 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001710 if (is_low_latency)
1711 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001712 /* ToDo: should use frame_size computed based on the format and
1713 channel_count here. */
1714 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001716 /* make sure the size is multiple of 32 bytes
1717 * At 48 kHz mono 16-bit PCM:
1718 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1719 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1720 */
1721 size += 0x1f;
1722 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001723
1724 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725}
1726
1727static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1728{
1729 struct stream_out *out = (struct stream_out *)stream;
1730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732}
1733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001734static int out_set_sample_rate(struct audio_stream *stream __unused,
1735 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736{
1737 return -ENOSYS;
1738}
1739
1740static size_t out_get_buffer_size(const struct audio_stream *stream)
1741{
1742 struct stream_out *out = (struct stream_out *)stream;
1743
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001744 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001746 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1747 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001749 return out->config.period_size *
1750 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751}
1752
1753static uint32_t out_get_channels(const struct audio_stream *stream)
1754{
1755 struct stream_out *out = (struct stream_out *)stream;
1756
1757 return out->channel_mask;
1758}
1759
1760static audio_format_t out_get_format(const struct audio_stream *stream)
1761{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 struct stream_out *out = (struct stream_out *)stream;
1763
1764 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765}
1766
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001767static int out_set_format(struct audio_stream *stream __unused,
1768 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769{
1770 return -ENOSYS;
1771}
1772
1773static int out_standby(struct audio_stream *stream)
1774{
1775 struct stream_out *out = (struct stream_out *)stream;
1776 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301778 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1779 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001780 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1781 /* Ignore standby in case of voip call because the voip output
1782 * stream is closed in adev_close_output_stream()
1783 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301784 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001785 return 0;
1786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001790 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001792 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 if (out->pcm) {
1794 pcm_close(out->pcm);
1795 out->pcm = NULL;
1796 }
1797 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001798 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800 out->gapless_mdata.encoder_delay = 0;
1801 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802 if (out->compr != NULL) {
1803 compress_close(out->compr);
1804 out->compr = NULL;
1805 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001808 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 }
1810 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001811 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 return 0;
1813}
1814
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001815static int out_dump(const struct audio_stream *stream __unused,
1816 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817{
1818 return 0;
1819}
1820
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1822{
1823 int ret = 0;
1824 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001825 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001826
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001828 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 return -EINVAL;
1830 }
1831
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001832 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1833 if (ret >= 0) {
1834 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1835 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1836 ALOGV("ADTS format is set in offload mode");
1837 }
1838 out->send_new_metadata = 1;
1839 }
1840
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301841 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001842
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1844 if(ret >= 0)
1845 is_meta_data_params = true;
1846 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, 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;
1849 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301850 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001851 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001852 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1853 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001854 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301855 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001856 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1858 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001859 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301860 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 }
1862
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001863 if(!is_meta_data_params) {
1864 ALOGV("%s: Not gapless meta data params", __func__);
1865 return 0;
1866 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 out->send_new_metadata = 1;
1868 ALOGV("%s new encoder delay %u and padding %u", __func__,
1869 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1870
1871 return 0;
1872}
1873
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001874static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1875{
1876 return out == adev->primary_output || out == adev->voice_tx_output;
1877}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1880{
1881 struct stream_out *out = (struct stream_out *)stream;
1882 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001883 struct audio_usecase *usecase;
1884 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 struct str_parms *parms;
1886 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001887 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001888 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889
sangwoobc677242013-08-08 16:53:43 +09001890 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301893 if (!parms)
1894 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001895 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1896 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001899 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301902 * When HDMI cable is unplugged/usb hs is disconnected the
1903 * music playback is paused and the policy manager sends routing=0
1904 * But the audioflingercontinues to write data until standby time
1905 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 * Avoid this by routing audio to speaker until standby.
1907 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301908 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1909 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001910 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001911 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1912 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 }
1914
1915 /*
1916 * select_devices() call below switches all the usecases on the same
1917 * backend to the new device. Refer to check_usecases_codec_backend() in
1918 * the select_devices(). But how do we undo this?
1919 *
1920 * For example, music playback is active on headset (deep-buffer usecase)
1921 * and if we go to ringtones and select a ringtone, low-latency usecase
1922 * will be started on headset+speaker. As we can't enable headset+speaker
1923 * and headset devices at the same time, select_devices() switches the music
1924 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1925 * So when the ringtone playback is completed, how do we undo the same?
1926 *
1927 * We are relying on the out_set_parameters() call on deep-buffer output,
1928 * once the ringtone playback is ended.
1929 * NOTE: We should not check if the current devices are same as new devices.
1930 * Because select_devices() must be called to switch back the music
1931 * playback to headset.
1932 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001933 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001934 out->devices = val;
1935
1936 if (!out->standby)
1937 select_devices(adev, out->usecase);
1938
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001939 if (output_drives_call(adev, out)) {
1940 if(!voice_is_in_call(adev)) {
1941 if (adev->mode == AUDIO_MODE_IN_CALL) {
1942 adev->current_call_output = out;
1943 ret = voice_start_call(adev);
1944 }
1945 } else {
1946 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001947 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001948 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001949 }
1950 }
1951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001953 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001955
1956 if (out == adev->primary_output) {
1957 pthread_mutex_lock(&adev->lock);
1958 audio_extn_set_parameters(adev, parms);
1959 pthread_mutex_unlock(&adev->lock);
1960 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001961 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001962 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001963 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001964
1965 audio_extn_dts_create_state_notifier_node(out->usecase);
1966 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1967 popcount(out->channel_mask),
1968 out->playback_started);
1969
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001970 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001971 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301974error:
Eric Laurent994a6932013-07-17 11:51:42 -07001975 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 return ret;
1977}
1978
1979static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1980{
1981 struct stream_out *out = (struct stream_out *)stream;
1982 struct str_parms *query = str_parms_create_str(keys);
1983 char *str;
1984 char value[256];
1985 struct str_parms *reply = str_parms_create();
1986 size_t i, j;
1987 int ret;
1988 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001989
1990 if (!query || !reply) {
1991 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1992 return NULL;
1993 }
1994
Eric Laurent994a6932013-07-17 11:51:42 -07001995 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1997 if (ret >= 0) {
1998 value[0] = '\0';
1999 i = 0;
2000 while (out->supported_channel_masks[i] != 0) {
2001 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2002 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2003 if (!first) {
2004 strcat(value, "|");
2005 }
2006 strcat(value, out_channels_name_to_enum_table[j].name);
2007 first = false;
2008 break;
2009 }
2010 }
2011 i++;
2012 }
2013 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2014 str = str_parms_to_str(reply);
2015 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002016 voice_extn_out_get_parameters(out, query, reply);
2017 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002018 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002019 free(str);
2020 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002023
2024 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2025 if (ret >= 0) {
2026 value[0] = '\0';
2027 i = 0;
2028 first = true;
2029 while (out->supported_formats[i] != 0) {
2030 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2031 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2032 if (!first) {
2033 strcat(value, "|");
2034 }
2035 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2036 first = false;
2037 break;
2038 }
2039 }
2040 i++;
2041 }
2042 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2043 str = str_parms_to_str(reply);
2044 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 str_parms_destroy(query);
2046 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002047 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 return str;
2049}
2050
2051static uint32_t out_get_latency(const struct audio_stream_out *stream)
2052{
2053 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002054 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055
Alexy Josephaa54c872014-12-03 02:46:47 -08002056 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002057 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002058 } else {
2059 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002061 }
2062
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302063 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002064 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065}
2066
2067static int out_set_volume(struct audio_stream_out *stream, float left,
2068 float right)
2069{
Eric Laurenta9024de2013-04-04 09:19:12 -07002070 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 int volume[2];
2072
Eric Laurenta9024de2013-04-04 09:19:12 -07002073 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2074 /* only take left channel into account: the API is for stereo anyway */
2075 out->muted = (left == 0.0f);
2076 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002077 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002078 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2079 /*
2080 * Set mute or umute on HDMI passthrough stream.
2081 * Only take left channel into account.
2082 * Mute is 0 and unmute 1
2083 */
2084 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2085 } else {
2086 char mixer_ctl_name[128];
2087 struct audio_device *adev = out->dev;
2088 struct mixer_ctl *ctl;
2089 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002090 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002092 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2093 "Compress Playback %d Volume", pcm_device_id);
2094 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2095 if (!ctl) {
2096 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2097 __func__, mixer_ctl_name);
2098 return -EINVAL;
2099 }
2100 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2101 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2102 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2103 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002105 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 return -ENOSYS;
2108}
2109
2110static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2111 size_t bytes)
2112{
2113 struct stream_out *out = (struct stream_out *)stream;
2114 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302115 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002116 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302119
Naresh Tanniru80659832014-06-04 18:17:56 +05302120 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002121 // increase written size during SSR to avoid mismatch
2122 // with the written frames count in AF
2123 if (!is_offload_usecase(out->usecase))
2124 out->written += bytes / (out->config.channels * sizeof(short));
2125
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302128 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302129 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002130 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302131 //during SSR for compress usecase we should return error to flinger
2132 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2133 pthread_mutex_unlock(&out->lock);
2134 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302135 }
2136 }
2137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002139 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002140 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002141 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2142 ret = voice_extn_compress_voip_start_output_stream(out);
2143 else
2144 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002145 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002148 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 goto exit;
2150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002153 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002154 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002155 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002156 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002157 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2158 out->send_new_metadata = 0;
2159 }
2160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302162 if (ret < 0)
2163 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002164 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002165 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302166 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302168 } else if (-ENETRESET == ret) {
2169 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2170 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2171 pthread_mutex_unlock(&out->lock);
2172 out_standby(&out->stream.common);
2173 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302175 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002177 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 out->playback_started = 1;
2179 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002180
2181 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2182 popcount(out->channel_mask),
2183 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184 }
2185 pthread_mutex_unlock(&out->lock);
2186 return ret;
2187 } else {
2188 if (out->pcm) {
2189 if (out->muted)
2190 memset((void *)buffer, 0, bytes);
2191 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002192 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2193 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2194 else
2195 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302196 if (ret < 0)
2197 ret = -errno;
2198 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002199 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 }
2202
2203exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302204 /* ToDo: There may be a corner case when SSR happens back to back during
2205 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302206 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302207 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302208 }
2209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 pthread_mutex_unlock(&out->lock);
2211
2212 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002213 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002214 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302215 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302216 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302217 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302218 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302219 out->standby = true;
2220 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002222 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302223 out_get_sample_rate(&out->stream.common));
2224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 }
2226 return bytes;
2227}
2228
2229static int out_get_render_position(const struct audio_stream_out *stream,
2230 uint32_t *dsp_frames)
2231{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302233 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002234
2235 if (dsp_frames == NULL)
2236 return -EINVAL;
2237
2238 *dsp_frames = 0;
2239 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002240 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 pthread_mutex_lock(&out->lock);
2242 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302243 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302245 if (ret < 0)
2246 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 ALOGVV("%s rendered frames %d sample_rate %d",
2248 __func__, *dsp_frames, out->sample_rate);
2249 }
2250 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302251 if (-ENETRESET == ret) {
2252 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2253 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2254 return -EINVAL;
2255 } else if(ret < 0) {
2256 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2257 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302258 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2259 /*
2260 * Handle corner case where compress session is closed during SSR
2261 * and timestamp is queried
2262 */
2263 ALOGE(" ERROR: sound card not active, return error");
2264 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302265 } else {
2266 return 0;
2267 }
Zhou Song32a556e2015-05-05 10:46:56 +08002268 } else if (audio_is_linear_pcm(out->format)) {
2269 *dsp_frames = out->written;
2270 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 } else
2272 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273}
2274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002275static int out_add_audio_effect(const struct audio_stream *stream __unused,
2276 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277{
2278 return 0;
2279}
2280
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002281static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2282 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283{
2284 return 0;
2285}
2286
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002287static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2288 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289{
2290 return -EINVAL;
2291}
2292
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002293static int out_get_presentation_position(const struct audio_stream_out *stream,
2294 uint64_t *frames, struct timespec *timestamp)
2295{
2296 struct stream_out *out = (struct stream_out *)stream;
2297 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002298 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002299
2300 pthread_mutex_lock(&out->lock);
2301
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002302 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002303 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302304 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002305 &out->sample_rate);
2306 ALOGVV("%s rendered frames %ld sample_rate %d",
2307 __func__, dsp_frames, out->sample_rate);
2308 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302309 if (ret < 0)
2310 ret = -errno;
2311 if (-ENETRESET == ret) {
2312 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2313 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2314 ret = -EINVAL;
2315 } else
2316 ret = 0;
2317
Eric Laurent949a0892013-09-20 09:20:13 -07002318 /* this is the best we can do */
2319 clock_gettime(CLOCK_MONOTONIC, timestamp);
2320 }
2321 } else {
2322 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002323 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002324 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2325 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002326 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002327 // This adjustment accounts for buffering after app processor.
2328 // It is based on estimated DSP latency per use case, rather than exact.
2329 signed_frames -=
2330 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2331
Eric Laurent949a0892013-09-20 09:20:13 -07002332 // It would be unusual for this value to be negative, but check just in case ...
2333 if (signed_frames >= 0) {
2334 *frames = signed_frames;
2335 ret = 0;
2336 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002337 }
2338 }
2339 }
2340
2341 pthread_mutex_unlock(&out->lock);
2342
2343 return ret;
2344}
2345
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346static int out_set_callback(struct audio_stream_out *stream,
2347 stream_callback_t callback, void *cookie)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350
2351 ALOGV("%s", __func__);
2352 pthread_mutex_lock(&out->lock);
2353 out->offload_callback = callback;
2354 out->offload_cookie = cookie;
2355 pthread_mutex_unlock(&out->lock);
2356 return 0;
2357}
2358
2359static int out_pause(struct audio_stream_out* stream)
2360{
2361 struct stream_out *out = (struct stream_out *)stream;
2362 int status = -ENOSYS;
2363 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002364 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002365 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 pthread_mutex_lock(&out->lock);
2367 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302368 struct audio_device *adev = out->dev;
2369 int snd_scard_state = get_snd_card_state(adev);
2370
2371 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2372 status = compress_pause(out->compr);
2373
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002375
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302376 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002377 audio_extn_dts_notify_playback_state(out->usecase, 0,
2378 out->sample_rate, popcount(out->channel_mask),
2379 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 }
2381 pthread_mutex_unlock(&out->lock);
2382 }
2383 return status;
2384}
2385
2386static int out_resume(struct audio_stream_out* stream)
2387{
2388 struct stream_out *out = (struct stream_out *)stream;
2389 int status = -ENOSYS;
2390 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002391 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002392 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 status = 0;
2394 pthread_mutex_lock(&out->lock);
2395 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302396 struct audio_device *adev = out->dev;
2397 int snd_scard_state = get_snd_card_state(adev);
2398
2399 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2400 status = compress_resume(out->compr);
2401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002403
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302404 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002405 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2406 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002407 }
2408 pthread_mutex_unlock(&out->lock);
2409 }
2410 return status;
2411}
2412
2413static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2414{
2415 struct stream_out *out = (struct stream_out *)stream;
2416 int status = -ENOSYS;
2417 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002418 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 pthread_mutex_lock(&out->lock);
2420 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2421 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2422 else
2423 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2424 pthread_mutex_unlock(&out->lock);
2425 }
2426 return status;
2427}
2428
2429static int out_flush(struct audio_stream_out* stream)
2430{
2431 struct stream_out *out = (struct stream_out *)stream;
2432 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002433 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002434 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002435 pthread_mutex_lock(&out->lock);
2436 stop_compressed_output_l(out);
2437 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002438 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 return 0;
2440 }
2441 return -ENOSYS;
2442}
2443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444/** audio_stream_in implementation **/
2445static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2446{
2447 struct stream_in *in = (struct stream_in *)stream;
2448
2449 return in->config.rate;
2450}
2451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002452static int in_set_sample_rate(struct audio_stream *stream __unused,
2453 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454{
2455 return -ENOSYS;
2456}
2457
2458static size_t in_get_buffer_size(const struct audio_stream *stream)
2459{
2460 struct stream_in *in = (struct stream_in *)stream;
2461
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002462 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2463 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002464 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2465 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002466
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002467 return in->config.period_size *
2468 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469}
2470
2471static uint32_t in_get_channels(const struct audio_stream *stream)
2472{
2473 struct stream_in *in = (struct stream_in *)stream;
2474
2475 return in->channel_mask;
2476}
2477
2478static audio_format_t in_get_format(const struct audio_stream *stream)
2479{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002480 struct stream_in *in = (struct stream_in *)stream;
2481
2482 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483}
2484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002485static int in_set_format(struct audio_stream *stream __unused,
2486 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487{
2488 return -ENOSYS;
2489}
2490
2491static int in_standby(struct audio_stream *stream)
2492{
2493 struct stream_in *in = (struct stream_in *)stream;
2494 struct audio_device *adev = in->dev;
2495 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302496 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2497 stream, in->usecase, use_case_table[in->usecase]);
2498
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002499 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2500 /* Ignore standby in case of voip call because the voip input
2501 * stream is closed in adev_close_input_stream()
2502 */
2503 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2504 return status;
2505 }
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002508 if (!in->standby && in->is_st_session) {
2509 ALOGD("%s: sound trigger pcm stop lab", __func__);
2510 audio_extn_sound_trigger_stop_lab(in);
2511 in->standby = 1;
2512 }
2513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002515 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002517 if (in->pcm) {
2518 pcm_close(in->pcm);
2519 in->pcm = NULL;
2520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 }
2524 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002525 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 return status;
2527}
2528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002529static int in_dump(const struct audio_stream *stream __unused,
2530 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531{
2532 return 0;
2533}
2534
2535static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2536{
2537 struct stream_in *in = (struct stream_in *)stream;
2538 struct audio_device *adev = in->dev;
2539 struct str_parms *parms;
2540 char *str;
2541 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002542 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302544 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 parms = str_parms_create_str(kvpairs);
2546
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302547 if (!parms)
2548 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002550 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002551
2552 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2553 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 val = atoi(value);
2555 /* no audio source uses val == 0 */
2556 if ((in->source != val) && (val != 0)) {
2557 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002558 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2559 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2560 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2561 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002562 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002563 err = voice_extn_compress_voip_open_input_stream(in);
2564 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002565 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002566 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002567 }
2568 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 }
2570 }
2571
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002572 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2573 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002575 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 in->device = val;
2577 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002578 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002579 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 }
2581 }
2582
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002583done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002585 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
2587 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302588error:
Eric Laurent994a6932013-07-17 11:51:42 -07002589 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 return ret;
2591}
2592
2593static char* in_get_parameters(const struct audio_stream *stream,
2594 const char *keys)
2595{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002596 struct stream_in *in = (struct stream_in *)stream;
2597 struct str_parms *query = str_parms_create_str(keys);
2598 char *str;
2599 char value[256];
2600 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002601
2602 if (!query || !reply) {
2603 ALOGE("in_get_parameters: failed to create query or reply");
2604 return NULL;
2605 }
2606
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002607 ALOGV("%s: enter: keys - %s", __func__, keys);
2608
2609 voice_extn_in_get_parameters(in, query, reply);
2610
2611 str = str_parms_to_str(reply);
2612 str_parms_destroy(query);
2613 str_parms_destroy(reply);
2614
2615 ALOGV("%s: exit: returns - %s", __func__, str);
2616 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617}
2618
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002619static int in_set_gain(struct audio_stream_in *stream __unused,
2620 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621{
2622 return 0;
2623}
2624
2625static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2626 size_t bytes)
2627{
2628 struct stream_in *in = (struct stream_in *)stream;
2629 struct audio_device *adev = in->dev;
2630 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302631 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302634
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002635 if (in->is_st_session) {
2636 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2637 /* Read from sound trigger HAL */
2638 audio_extn_sound_trigger_read(in, buffer, bytes);
2639 pthread_mutex_unlock(&in->lock);
2640 return bytes;
2641 }
2642
2643 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2644 ALOGD(" %s: sound card is not active/SSR state", __func__);
2645 ret= -EIO;;
2646 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302647 }
2648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002650 pthread_mutex_lock(&adev->lock);
2651 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2652 ret = voice_extn_compress_voip_start_input_stream(in);
2653 else
2654 ret = start_input_stream(in);
2655 pthread_mutex_unlock(&adev->lock);
2656 if (ret != 0) {
2657 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 }
2659 in->standby = 0;
2660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661
2662 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002663 if (audio_extn_ssr_get_enabled() &&
2664 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002665 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002666 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2667 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002668 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2669 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002670 else
2671 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302672 if (ret < 0)
2673 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 }
2675
2676 /*
2677 * Instead of writing zeroes here, we could trust the hardware
2678 * to always provide zeroes when muted.
2679 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302680 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2681 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 memset(buffer, 0, bytes);
2683
2684exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302685 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302686 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002687 if (-ENETRESET == ret)
2688 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 pthread_mutex_unlock(&in->lock);
2691
2692 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302694 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302695 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302697 in->standby = true;
2698 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302699 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002701 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002702 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302703 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
2705 return bytes;
2706}
2707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002708static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709{
2710 return 0;
2711}
2712
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713static int add_remove_audio_effect(const struct audio_stream *stream,
2714 effect_handle_t effect,
2715 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 struct stream_in *in = (struct stream_in *)stream;
2718 int status = 0;
2719 effect_descriptor_t desc;
2720
2721 status = (*effect)->get_descriptor(effect, &desc);
2722 if (status != 0)
2723 return status;
2724
2725 pthread_mutex_lock(&in->lock);
2726 pthread_mutex_lock(&in->dev->lock);
2727 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2728 in->enable_aec != enable &&
2729 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2730 in->enable_aec = enable;
2731 if (!in->standby)
2732 select_devices(in->dev, in->usecase);
2733 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002734 if (in->enable_ns != enable &&
2735 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2736 in->enable_ns = enable;
2737 if (!in->standby)
2738 select_devices(in->dev, in->usecase);
2739 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002740 pthread_mutex_unlock(&in->dev->lock);
2741 pthread_mutex_unlock(&in->lock);
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 return 0;
2744}
2745
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002746static int in_add_audio_effect(const struct audio_stream *stream,
2747 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748{
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002750 return add_remove_audio_effect(stream, effect, true);
2751}
2752
2753static int in_remove_audio_effect(const struct audio_stream *stream,
2754 effect_handle_t effect)
2755{
Eric Laurent994a6932013-07-17 11:51:42 -07002756 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002757 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758}
2759
2760static int adev_open_output_stream(struct audio_hw_device *dev,
2761 audio_io_handle_t handle,
2762 audio_devices_t devices,
2763 audio_output_flags_t flags,
2764 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002765 struct audio_stream_out **stream_out,
2766 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767{
2768 struct audio_device *adev = (struct audio_device *)dev;
2769 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002770 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002771 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302774
2775 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2776 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2777 ALOGE(" sound card is not active rejecting compress output open request");
2778 return -EINVAL;
2779 }
2780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2782
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302783 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2784 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2785 devices, flags, &out->stream);
2786
2787
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002788 if (!out) {
2789 return -ENOMEM;
2790 }
2791
Haynes Mathew George204045b2015-02-25 20:32:03 -08002792 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2793 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 if (devices == AUDIO_DEVICE_NONE)
2796 devices = AUDIO_DEVICE_OUT_SPEAKER;
2797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 out->flags = flags;
2799 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002800 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002801 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002802 out->sample_rate = config->sample_rate;
2803 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2804 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002805 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002806 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002807 out->non_blocking = 0;
2808 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809
2810 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002811 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2812 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002813 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2814 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2815
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002816 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002817 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2818 ret = read_hdmi_channel_masks(out);
2819
2820 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2821 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002822 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002823 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002824 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002825
2826 if (config->sample_rate == 0)
2827 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2828 if (config->channel_mask == 0)
2829 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2830
2831 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2834 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002836 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002838 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2839 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002840 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002841 ret = voice_extn_compress_voip_open_output_stream(out);
2842 if (ret != 0) {
2843 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2844 __func__, ret);
2845 goto error_open;
2846 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2848 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2849 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2850 ALOGE("%s: Unsupported Offload information", __func__);
2851 ret = -EINVAL;
2852 goto error_open;
2853 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002854
2855 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2856 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2857 ALOGV("read and update_pass through formats");
2858 ret = audio_extn_dolby_update_passt_formats(adev, out);
2859 if(ret != 0) {
2860 goto error_open;
2861 }
2862 if(config->offload_info.format == 0)
2863 config->offload_info.format = out->supported_formats[0];
2864 }
2865
Mingming Yin90310102013-11-13 16:57:00 -08002866 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002867 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 ALOGE("%s: Unsupported audio format", __func__);
2869 ret = -EINVAL;
2870 goto error_open;
2871 }
2872
2873 out->compr_config.codec = (struct snd_codec *)
2874 calloc(1, sizeof(struct snd_codec));
2875
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002876 if (!out->compr_config.codec) {
2877 ret = -ENOMEM;
2878 goto error_open;
2879 }
2880
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002881 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 if (config->offload_info.channel_mask)
2883 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002884 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002886 config->offload_info.channel_mask = config->channel_mask;
2887 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002888 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->sample_rate = config->offload_info.sample_rate;
2890
2891 out->stream.set_callback = out_set_callback;
2892 out->stream.pause = out_pause;
2893 out->stream.resume = out_resume;
2894 out->stream.drain = out_drain;
2895 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002896 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002898 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002899 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002900 audio_extn_dolby_get_snd_codec_id(adev, out,
2901 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002902 else
2903 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat2ec445f2015-07-23 18:02:31 +05302905 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002907 platform_get_pcm_offload_buffer_size(&config->offload_info);
2908 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2909 out->compr_config.fragment_size =
2910 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002911 } else {
2912 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002914 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2916 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002917 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 out->compr_config.codec->bit_rate =
2919 config->offload_info.bit_rate;
2920 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002921 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302923 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 /*TODO: Do we need to change it for passthrough */
2925 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926
Mingming Yin3ee55c62014-08-04 14:23:35 -07002927 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2928 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2930 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002931 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002932 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2933
Mingming Yin3ee55c62014-08-04 14:23:35 -07002934 if (out->bit_width == 24) {
2935 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2936 }
2937
Amit Shekhar6f461b12014-08-01 14:52:58 -07002938 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302939 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002940
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2942 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002943
Mingming Yin497419f2015-07-01 16:57:32 -07002944 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002945 //this flag is set from framework only if its for PCM formats
2946 //no need to check for PCM format again
2947 out->non_blocking = 0;
2948 out->use_small_bufs = true;
2949 ALOGI("Keep write blocking for small buff: non_blockling %d",
2950 out->non_blocking);
2951 }
2952
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002953 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002954 out->offload_state = OFFLOAD_STATE_IDLE;
2955 out->playback_started = 0;
2956
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002957 audio_extn_dts_create_state_notifier_node(out->usecase);
2958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 create_offload_callback_thread(out);
2960 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2961 __func__, config->offload_info.version,
2962 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002963 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002964 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002965 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2966 ret = voice_check_and_set_incall_music_usecase(adev, out);
2967 if (ret != 0) {
2968 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2969 __func__, ret);
2970 goto error_open;
2971 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002972 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2973 if (config->sample_rate == 0)
2974 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2975 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2976 config->sample_rate != 8000) {
2977 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2978 ret = -EINVAL;
2979 goto error_open;
2980 }
2981 out->sample_rate = config->sample_rate;
2982 out->config.rate = config->sample_rate;
2983 if (config->format == AUDIO_FORMAT_DEFAULT)
2984 config->format = AUDIO_FORMAT_PCM_16_BIT;
2985 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2986 config->format = AUDIO_FORMAT_PCM_16_BIT;
2987 ret = -EINVAL;
2988 goto error_open;
2989 }
2990 out->format = config->format;
2991 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2992 out->config = pcm_config_afe_proxy_playback;
2993 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002994 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002995 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2997 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002999 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3000 format = AUDIO_FORMAT_PCM_16_BIT;
3001 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3002 out->config = pcm_config_deep_buffer;
3003 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003004 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003005 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003006 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003007 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003008 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003009 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 }
3011
Amit Shekhar1d896042014-10-03 13:16:09 -07003012 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3013 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003014 /* TODO remove this hardcoding and check why width is zero*/
3015 if (out->bit_width == 0)
3016 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003017 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3018 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003019 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003020 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003021 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3022 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3023 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003024 if(adev->primary_output == NULL)
3025 adev->primary_output = out;
3026 else {
3027 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003028 ret = -EEXIST;
3029 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003030 }
3031 }
3032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 /* Check if this usecase is already existing */
3034 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003035 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3036 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003039 ret = -EEXIST;
3040 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 }
3042 pthread_mutex_unlock(&adev->lock);
3043
3044 out->stream.common.get_sample_rate = out_get_sample_rate;
3045 out->stream.common.set_sample_rate = out_set_sample_rate;
3046 out->stream.common.get_buffer_size = out_get_buffer_size;
3047 out->stream.common.get_channels = out_get_channels;
3048 out->stream.common.get_format = out_get_format;
3049 out->stream.common.set_format = out_set_format;
3050 out->stream.common.standby = out_standby;
3051 out->stream.common.dump = out_dump;
3052 out->stream.common.set_parameters = out_set_parameters;
3053 out->stream.common.get_parameters = out_get_parameters;
3054 out->stream.common.add_audio_effect = out_add_audio_effect;
3055 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3056 out->stream.get_latency = out_get_latency;
3057 out->stream.set_volume = out_set_volume;
3058 out->stream.write = out_write;
3059 out->stream.get_render_position = out_get_render_position;
3060 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003061 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003064 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003065 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066
3067 config->format = out->stream.common.get_format(&out->stream.common);
3068 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3069 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3070
3071 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303072 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3073 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003074
3075 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3076 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3077 popcount(out->channel_mask), out->playback_started);
3078
Eric Laurent994a6932013-07-17 11:51:42 -07003079 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003081
3082error_open:
3083 free(out);
3084 *stream_out = NULL;
3085 ALOGD("%s: exit: ret %d", __func__, ret);
3086 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087}
3088
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003089static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 struct audio_stream_out *stream)
3091{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 struct stream_out *out = (struct stream_out *)stream;
3093 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003094 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303096 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3097
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003098 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303099 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003100 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303101 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003102 if(ret != 0)
3103 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3104 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003105 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003106 out_standby(&stream->common);
3107
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003108 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003109 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003111 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 if (out->compr_config.codec != NULL)
3113 free(out->compr_config.codec);
3114 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003115
3116 if (adev->voice_tx_output == out)
3117 adev->voice_tx_output = NULL;
3118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 pthread_cond_destroy(&out->cond);
3120 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003122 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123}
3124
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003125static void close_compress_sessions(struct audio_device *adev)
3126{
Mingming Yin7b762e72015-03-04 13:47:32 -08003127 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303128 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003129 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303131
3132 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003133 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303134 if (is_offload_usecase(usecase->id)) {
3135 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003136 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3137 out = usecase->stream.out;
3138 pthread_mutex_unlock(&adev->lock);
3139 out_standby(&out->stream.common);
3140 pthread_mutex_lock(&adev->lock);
3141 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303142 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003143 }
3144 pthread_mutex_unlock(&adev->lock);
3145}
3146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3148{
3149 struct audio_device *adev = (struct audio_device *)dev;
3150 struct str_parms *parms;
3151 char *str;
3152 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003153 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 int ret;
3155 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003157 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303160 if (!parms)
3161 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3163 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303164 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303165 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303166 struct listnode *node;
3167 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303168 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303169 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003170 //close compress sessions on OFFLINE status
3171 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303172 } else if (strstr(snd_card_status, "ONLINE")) {
3173 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303174 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003175 //send dts hpx license if enabled
3176 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303177 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303178 }
3179
3180 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003181 status = voice_set_parameters(adev, parms);
3182 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003183 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003185 status = platform_set_parameters(adev->platform, parms);
3186 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003187 goto done;
3188
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003189 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3190 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003191 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3193 adev->bluetooth_nrec = true;
3194 else
3195 adev->bluetooth_nrec = false;
3196 }
3197
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3199 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3201 adev->screen_off = false;
3202 else
3203 adev->screen_off = true;
3204 }
3205
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 ret = str_parms_get_int(parms, "rotation", &val);
3207 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003208 bool reverse_speakers = false;
3209 switch(val) {
3210 // FIXME: note that the code below assumes that the speakers are in the correct placement
3211 // relative to the user when the device is rotated 90deg from its default rotation. This
3212 // assumption is device-specific, not platform-specific like this code.
3213 case 270:
3214 reverse_speakers = true;
3215 break;
3216 case 0:
3217 case 90:
3218 case 180:
3219 break;
3220 default:
3221 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003222 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003223 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003224 if (status == 0) {
3225 if (adev->speaker_lr_swap != reverse_speakers) {
3226 adev->speaker_lr_swap = reverse_speakers;
3227 // only update the selected device if there is active pcm playback
3228 struct audio_usecase *usecase;
3229 struct listnode *node;
3230 list_for_each(node, &adev->usecase_list) {
3231 usecase = node_to_item(node, struct audio_usecase, list);
3232 if (usecase->type == PCM_PLAYBACK) {
3233 select_devices(adev, usecase->id);
3234 break;
3235 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003236 }
3237 }
3238 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003239 }
3240
Mingming Yin514a8bc2014-07-29 15:22:21 -07003241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3242 if (ret >= 0) {
3243 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3244 adev->bt_wb_speech_enabled = true;
3245 else
3246 adev->bt_wb_speech_enabled = false;
3247 }
3248
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003249 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3250 if (ret >= 0) {
3251 val = atoi(value);
3252 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3253 ALOGV("cache new edid");
3254 platform_cache_edid(adev->platform);
3255 }
3256 }
3257
3258 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3259 if (ret >= 0) {
3260 val = atoi(value);
3261 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3262 ALOGV("invalidate cached edid");
3263 platform_invalidate_edid(adev->platform);
3264 }
3265 }
3266
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003267 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003268
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003269done:
3270 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003271 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303272error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003273 ALOGV("%s: exit with code(%d)", __func__, status);
3274 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
3277static char* adev_get_parameters(const struct audio_hw_device *dev,
3278 const char *keys)
3279{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003280 struct audio_device *adev = (struct audio_device *)dev;
3281 struct str_parms *reply = str_parms_create();
3282 struct str_parms *query = str_parms_create_str(keys);
3283 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303284 char value[256] = {0};
3285 int ret = 0;
3286
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003287 if (!query || !reply) {
3288 ALOGE("adev_get_parameters: failed to create query or reply");
3289 return NULL;
3290 }
3291
Naresh Tannirud7205b62014-06-20 02:54:48 +05303292 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3293 sizeof(value));
3294 if (ret >=0) {
3295 int val = 1;
3296 pthread_mutex_lock(&adev->snd_card_status.lock);
3297 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3298 val = 0;
3299 pthread_mutex_unlock(&adev->snd_card_status.lock);
3300 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3301 goto exit;
3302 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003303
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003304 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003305 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003306 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003307 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303308 pthread_mutex_unlock(&adev->lock);
3309
Naresh Tannirud7205b62014-06-20 02:54:48 +05303310exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003311 str = str_parms_to_str(reply);
3312 str_parms_destroy(query);
3313 str_parms_destroy(reply);
3314
3315 ALOGV("%s: exit: returns - %s", __func__, str);
3316 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003319static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320{
3321 return 0;
3322}
3323
3324static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3325{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003326 int ret;
3327 struct audio_device *adev = (struct audio_device *)dev;
3328 pthread_mutex_lock(&adev->lock);
3329 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003330 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003331 pthread_mutex_unlock(&adev->lock);
3332 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3336 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return -ENOSYS;
3339}
3340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003341static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3342 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return -ENOSYS;
3345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3348 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return -ENOSYS;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3354 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355{
3356 return -ENOSYS;
3357}
3358
3359static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3360{
3361 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 pthread_mutex_lock(&adev->lock);
3364 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003365 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003367 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3368 voice_is_in_call(adev)) {
3369 voice_stop_call(adev);
3370 adev->current_call_output = NULL;
3371 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 }
3373 pthread_mutex_unlock(&adev->lock);
3374 return 0;
3375}
3376
3377static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3378{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003379 int ret;
3380
3381 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003382 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003383 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3384 pthread_mutex_unlock(&adev->lock);
3385
3386 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387}
3388
3389static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3390{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003391 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 return 0;
3393}
3394
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003395static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396 const struct audio_config *config)
3397{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003398 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003400 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3401 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402}
3403
3404static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003405 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 audio_devices_t devices,
3407 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003408 struct audio_stream_in **stream_in,
3409 audio_input_flags_t flags __unused,
3410 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003411 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412{
3413 struct audio_device *adev = (struct audio_device *)dev;
3414 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003415 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003416 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003417 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 *stream_in = NULL;
3420 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3421 return -EINVAL;
3422
3423 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003424
3425 if (!in) {
3426 ALOGE("failed to allocate input stream");
3427 return -ENOMEM;
3428 }
3429
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303430 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003431 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3432 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003434 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 in->stream.common.get_sample_rate = in_get_sample_rate;
3437 in->stream.common.set_sample_rate = in_set_sample_rate;
3438 in->stream.common.get_buffer_size = in_get_buffer_size;
3439 in->stream.common.get_channels = in_get_channels;
3440 in->stream.common.get_format = in_get_format;
3441 in->stream.common.set_format = in_set_format;
3442 in->stream.common.standby = in_standby;
3443 in->stream.common.dump = in_dump;
3444 in->stream.common.set_parameters = in_set_parameters;
3445 in->stream.common.get_parameters = in_get_parameters;
3446 in->stream.common.add_audio_effect = in_add_audio_effect;
3447 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3448 in->stream.set_gain = in_set_gain;
3449 in->stream.read = in_read;
3450 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3451
3452 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003453 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 in->standby = 1;
3456 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003457 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458
3459 /* Update config params with the requested sample rate and channels */
3460 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003461 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3462 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3463 is_low_latency = true;
3464#if LOW_LATENCY_CAPTURE_USE_CASE
3465 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3466#endif
3467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003470 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003472 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303473 if (adev->mode != AUDIO_MODE_IN_CALL) {
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003477 if (config->sample_rate == 0)
3478 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3479 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3480 config->sample_rate != 8000) {
3481 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3482 ret = -EINVAL;
3483 goto err_open;
3484 }
3485 if (config->format == AUDIO_FORMAT_DEFAULT)
3486 config->format = AUDIO_FORMAT_PCM_16_BIT;
3487 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3488 config->format = AUDIO_FORMAT_PCM_16_BIT;
3489 ret = -EINVAL;
3490 goto err_open;
3491 }
3492
3493 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3494 in->config = pcm_config_afe_proxy_record;
3495 in->config.channels = channel_count;
3496 in->config.rate = config->sample_rate;
3497 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003498 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003499 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003500 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3501 ret = -EINVAL;
3502 goto err_open;
3503 }
3504 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003505 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003506 }
Mingming Yine62d7842013-10-25 16:26:03 -07003507 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003508 audio_extn_compr_cap_format_supported(config->format) &&
3509 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003510 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003511 } else {
3512 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003513 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003514 buffer_size = get_input_buffer_size(config->sample_rate,
3515 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003516 channel_count,
3517 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003519 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3520 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3521 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3522 (in->config.rate == 8000 || in->config.rate == 16000) &&
3523 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3524 voice_extn_compress_voip_open_input_stream(in);
3525 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003528 /* This stream could be for sound trigger lab,
3529 get sound trigger pcm if present */
3530 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303531 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003534 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003535 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536
3537err_open:
3538 free(in);
3539 *stream_in = NULL;
3540 return ret;
3541}
3542
3543static void adev_close_input_stream(struct audio_hw_device *dev,
3544 struct audio_stream_in *stream)
3545{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003546 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003547 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003548 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303549
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303550 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003551
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303552 /* Disable echo reference while closing input stream */
3553 platform_set_echo_reference(adev->platform, false);
3554
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003555 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303556 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003557 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303558 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003559 if (ret != 0)
3560 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3561 __func__, ret);
3562 } else
3563 in_standby(&stream->common);
3564
Mingming Yin7b762e72015-03-04 13:47:32 -08003565 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003566 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003567 audio_extn_ssr_deinit();
3568 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569
Mingming Yine62d7842013-10-25 16:26:03 -07003570 if(audio_extn_compr_cap_enabled() &&
3571 audio_extn_compr_cap_format_supported(in->config.format))
3572 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003573
3574 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 return;
3576}
3577
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003578static int adev_dump(const audio_hw_device_t *device __unused,
3579 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580{
3581 return 0;
3582}
3583
3584static int adev_close(hw_device_t *device)
3585{
3586 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003587
3588 if (!adev)
3589 return 0;
3590
3591 pthread_mutex_lock(&adev_init_lock);
3592
3593 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003594 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003595 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003596 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003597 audio_route_free(adev->audio_route);
3598 free(adev->snd_dev_ref_cnt);
3599 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003600 free(device);
3601 adev = NULL;
3602 }
3603 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 return 0;
3605}
3606
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003607/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3608 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3609 * just that it _might_ work.
3610 */
3611static int period_size_is_plausible_for_low_latency(int period_size)
3612{
3613 switch (period_size) {
3614 case 160:
3615 case 240:
3616 case 320:
3617 case 480:
3618 return 1;
3619 default:
3620 return 0;
3621 }
3622}
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624static int adev_open(const hw_module_t *module, const char *name,
3625 hw_device_t **device)
3626{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003627 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003629 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3631
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003632 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003633 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003634 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003635 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003636 ALOGD("%s: returning existing instance of adev", __func__);
3637 ALOGD("%s: exit", __func__);
3638 pthread_mutex_unlock(&adev_init_lock);
3639 return 0;
3640 }
3641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 adev = calloc(1, sizeof(struct audio_device));
3643
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003644 if (!adev) {
3645 pthread_mutex_unlock(&adev_init_lock);
3646 return -ENOMEM;
3647 }
3648
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003649 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3652 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3653 adev->device.common.module = (struct hw_module_t *)module;
3654 adev->device.common.close = adev_close;
3655
3656 adev->device.init_check = adev_init_check;
3657 adev->device.set_voice_volume = adev_set_voice_volume;
3658 adev->device.set_master_volume = adev_set_master_volume;
3659 adev->device.get_master_volume = adev_get_master_volume;
3660 adev->device.set_master_mute = adev_set_master_mute;
3661 adev->device.get_master_mute = adev_get_master_mute;
3662 adev->device.set_mode = adev_set_mode;
3663 adev->device.set_mic_mute = adev_set_mic_mute;
3664 adev->device.get_mic_mute = adev_get_mic_mute;
3665 adev->device.set_parameters = adev_set_parameters;
3666 adev->device.get_parameters = adev_get_parameters;
3667 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3668 adev->device.open_output_stream = adev_open_output_stream;
3669 adev->device.close_output_stream = adev_close_output_stream;
3670 adev->device.open_input_stream = adev_open_input_stream;
3671 adev->device.close_input_stream = adev_close_input_stream;
3672 adev->device.dump = adev_dump;
3673
3674 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003676 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003677 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003680 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003681 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003682 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003683 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003684 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003685 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003686 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303687
3688 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3689 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003691 adev->platform = platform_init(adev);
3692 if (!adev->platform) {
3693 free(adev->snd_dev_ref_cnt);
3694 free(adev);
3695 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3696 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003697 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003698 return -EINVAL;
3699 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003700
Naresh Tanniru4c630392014-05-12 01:05:52 +05303701 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3702
Eric Laurentc4aef752013-09-12 17:45:53 -07003703 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3704 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3705 if (adev->visualizer_lib == NULL) {
3706 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3707 } else {
3708 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3709 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003710 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003711 "visualizer_hal_start_output");
3712 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003713 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003714 "visualizer_hal_stop_output");
3715 }
3716 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003717 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003718 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003719
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003720 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3721 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3722 if (adev->offload_effects_lib == NULL) {
3723 ALOGE("%s: DLOPEN failed for %s", __func__,
3724 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3725 } else {
3726 ALOGV("%s: DLOPEN successful for %s", __func__,
3727 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3728 adev->offload_effects_start_output =
3729 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3730 "offload_effects_bundle_hal_start_output");
3731 adev->offload_effects_stop_output =
3732 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3733 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003734 adev->offload_effects_set_hpx_state =
3735 (int (*)(bool))dlsym(adev->offload_effects_lib,
3736 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003737 }
3738 }
3739
Mingming Yin514a8bc2014-07-29 15:22:21 -07003740 adev->bt_wb_speech_enabled = false;
3741
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003742 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 *device = &adev->device.common;
3744
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003745 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3746 &adev->streams_output_cfg_list);
3747
Kiran Kandi910e1862013-10-29 13:29:42 -07003748 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003749
3750 char value[PROPERTY_VALUE_MAX];
3751 int trial;
3752 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3753 trial = atoi(value);
3754 if (period_size_is_plausible_for_low_latency(trial)) {
3755 pcm_config_low_latency.period_size = trial;
3756 pcm_config_low_latency.start_threshold = trial / 4;
3757 pcm_config_low_latency.avail_min = trial / 4;
3758 configured_low_latency_capture_period_size = trial;
3759 }
3760 }
3761 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3762 trial = atoi(value);
3763 if (period_size_is_plausible_for_low_latency(trial)) {
3764 configured_low_latency_capture_period_size = trial;
3765 }
3766 }
3767
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003768 pthread_mutex_unlock(&adev_init_lock);
3769
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 return 0;
3772}
3773
3774static struct hw_module_methods_t hal_module_methods = {
3775 .open = adev_open,
3776};
3777
3778struct audio_module HAL_MODULE_INFO_SYM = {
3779 .common = {
3780 .tag = HARDWARE_MODULE_TAG,
3781 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3782 .hal_api_version = HARDWARE_HAL_API_VERSION,
3783 .id = AUDIO_HARDWARE_MODULE_ID,
3784 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003785 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 .methods = &hal_module_methods,
3787 },
3788};