blob: 002da80b1ae5aea81fa85db523bccdfd7e01af1f [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
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800489 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200567 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568 audio_extn_sound_trigger_update_device_status(snd_device,
569 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530570 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800571 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 return 0;
575}
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577static void check_usecases_codec_backend(struct audio_device *adev,
578 struct audio_usecase *uc_info,
579 snd_device_t snd_device)
580{
581 struct listnode *node;
582 struct audio_usecase *usecase;
583 bool switch_device[AUDIO_USECASE_MAX];
584 int i, num_uc_to_switch = 0;
585
586 /*
587 * This function is to make sure that all the usecases that are active on
588 * the hardware codec backend are always routed to any one device that is
589 * handled by the hardware codec.
590 * For example, if low-latency and deep-buffer usecases are currently active
591 * on speaker and out_set_parameters(headset) is received on low-latency
592 * output, then we have to make sure deep-buffer is also switched to headset,
593 * because of the limitation that both the devices cannot be enabled
594 * at the same time as they share the same backend.
595 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700596 /*
597 * This call is to check if we need to force routing for a particular stream
598 * If there is a backend configuration change for the device when a
599 * new stream starts, then ADM needs to be closed and re-opened with the new
600 * configuraion. This call check if we need to re-route all the streams
601 * associated with the backend. Touch tone + 24 bit playback.
602 */
603 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800606 * specified usecase.
607 * For native(44.1k) usecases, we don't need this as it uses a different
608 * backend, but we need to make sure that we reconfigure the backend
609 * if there is bit_width change, this should not affect shared backend
610 * usecases.
611 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 for (i = 0; i < AUDIO_USECASE_MAX; i++)
613 switch_device[i] = false;
614
615 list_for_each(node, &adev->usecase_list) {
616 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800617 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700619 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800620 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND
621 && usecase->stream.out->sample_rate != OUTPUT_SAMPLING_RATE_44100) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
623 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700624 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700625 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 switch_device[usecase->id] = true;
627 num_uc_to_switch++;
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800628 } else if (usecase->type == PCM_PLAYBACK &&
629 usecase->stream.out->sample_rate ==
630 OUTPUT_SAMPLING_RATE_44100 && force_routing){
631 disable_audio_route(adev, usecase);
632 switch_device[usecase->id] = true;
633 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 }
635 }
636
637 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700638 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530640 /* Make sure the previous devices to be disabled first and then enable the
641 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 list_for_each(node, &adev->usecase_list) {
643 usecase = node_to_item(node, struct audio_usecase, list);
644 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700645 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 }
647 }
648
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700649 list_for_each(node, &adev->usecase_list) {
650 usecase = node_to_item(node, struct audio_usecase, list);
651 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700652 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700653 }
654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 /* Re-route all the usecases on the shared backend other than the
657 specified usecase to new snd devices */
658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 /* Update the out_snd_device only before enabling the audio route */
661 if (switch_device[usecase->id] ) {
662 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800663 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530664 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 }
668}
669
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670static void check_and_route_capture_usecases(struct audio_device *adev,
671 struct audio_usecase *uc_info,
672 snd_device_t snd_device)
673{
674 struct listnode *node;
675 struct audio_usecase *usecase;
676 bool switch_device[AUDIO_USECASE_MAX];
677 int i, num_uc_to_switch = 0;
678
679 /*
680 * This function is to make sure that all the active capture usecases
681 * are always routed to the same input sound device.
682 * For example, if audio-record and voice-call usecases are currently
683 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
684 * is received for voice call then we have to make sure that audio-record
685 * usecase is also switched to earpiece i.e. voice-dmic-ef,
686 * because of the limitation that two devices cannot be enabled
687 * at the same time if they share the same backend.
688 */
689 for (i = 0; i < AUDIO_USECASE_MAX; i++)
690 switch_device[i] = false;
691
692 list_for_each(node, &adev->usecase_list) {
693 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700696 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530697 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700698 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700699 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
700 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700701 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 switch_device[usecase->id] = true;
704 num_uc_to_switch++;
705 }
706 }
707
708 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700709 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530711 /* Make sure the previous devices to be disabled first and then enable the
712 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700713 list_for_each(node, &adev->usecase_list) {
714 usecase = node_to_item(node, struct audio_usecase, list);
715 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700716 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 }
718 }
719
720 list_for_each(node, &adev->usecase_list) {
721 usecase = node_to_item(node, struct audio_usecase, list);
722 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700723 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 }
725 }
726
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 /* Re-route all the usecases on the shared backend other than the
728 specified usecase to new snd devices */
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 /* Update the in_snd_device only before enabling the audio route */
732 if (switch_device[usecase->id] ) {
733 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800734 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530735 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 }
737 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 }
739}
740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700742static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700744 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700745 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746
747 switch (channels) {
748 /*
749 * Do not handle stereo output in Multi-channel cases
750 * Stereo case is handled in normal playback path
751 */
752 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700753 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759 break;
760 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 break;
769 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700770 ALOGE("HDMI does not support multi channel playback");
771 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772 break;
773 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700774 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775}
776
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800777audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
778 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700779{
780 struct audio_usecase *usecase;
781 struct listnode *node;
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800785 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700786 ALOGV("%s: usecase id %d", __func__, usecase->id);
787 return usecase->id;
788 }
789 }
790 return USECASE_INVALID;
791}
792
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700793struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700794 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795{
796 struct audio_usecase *usecase;
797 struct listnode *node;
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (usecase->id == uc_id)
802 return usecase;
803 }
804 return NULL;
805}
806
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700807int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800809 snd_device_t out_snd_device = SND_DEVICE_NONE;
810 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 struct audio_usecase *usecase = NULL;
812 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800814 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800815 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800816 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 usecase = get_usecase_from_list(adev, uc_id);
820 if (usecase == NULL) {
821 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
822 return -EINVAL;
823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800825 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800826 (usecase->type == VOIP_CALL) ||
827 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700828 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800829 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 usecase->devices = usecase->stream.out->devices;
832 } else {
833 /*
834 * If the voice call is active, use the sound devices of voice call usecase
835 * so that it would not result any device switch. All the usecases will
836 * be switched to new device when select_devices() is called for voice call
837 * usecase. This is to avoid switching devices for voice call when
838 * check_usecases_codec_backend() is called below.
839 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700840 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700841 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800842 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700843 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
844 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 in_snd_device = vc_usecase->in_snd_device;
846 out_snd_device = vc_usecase->out_snd_device;
847 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800848 } else if (voice_extn_compress_voip_is_active(adev)) {
849 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700850 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530851 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700852 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800853 in_snd_device = voip_usecase->in_snd_device;
854 out_snd_device = voip_usecase->out_snd_device;
855 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800856 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800857 hfp_ucid = audio_extn_hfp_get_usecase();
858 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800860 in_snd_device = hfp_usecase->in_snd_device;
861 out_snd_device = hfp_usecase->out_snd_device;
862 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 }
864 if (usecase->type == PCM_PLAYBACK) {
865 usecase->devices = usecase->stream.out->devices;
866 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700867 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800869 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700870 if (usecase->stream.out == adev->primary_output &&
871 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800872 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
873 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 select_devices(adev, adev->active_input->usecase);
875 }
876 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 } else if (usecase->type == PCM_CAPTURE) {
878 usecase->devices = usecase->stream.in->device;
879 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700881 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530882 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
883 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
884 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
885 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800887 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
889 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 }
895
896 if (out_snd_device == usecase->out_snd_device &&
897 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898 return 0;
899 }
900
sangwoobc677242013-08-08 16:53:43 +0900901 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700902 out_snd_device, platform_get_snd_device_name(out_snd_device),
903 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 /*
906 * Limitation: While in call, to do a device switch we need to disable
907 * and enable both RX and TX devices though one of them is same as current
908 * device.
909 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700910 if ((usecase->type == VOICE_CALL) &&
911 (usecase->in_snd_device != SND_DEVICE_NONE) &&
912 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700913 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800914 }
915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 /* Disable current sound devices */
917 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700918 disable_audio_route(adev, usecase);
919 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 }
921
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700923 disable_audio_route(adev, usecase);
924 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800925 }
926
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800927 /* Applicable only on the targets that has external modem.
928 * New device information should be sent to modem before enabling
929 * the devices to reduce in-call device switch time.
930 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700931 if ((usecase->type == VOICE_CALL) &&
932 (usecase->in_snd_device != SND_DEVICE_NONE) &&
933 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800934 status = platform_switch_voice_call_enable_device_config(adev->platform,
935 out_snd_device,
936 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700937 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 /* Enable new sound devices */
940 if (out_snd_device != SND_DEVICE_NONE) {
941 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
942 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700943 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 }
945
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 if (in_snd_device != SND_DEVICE_NONE) {
947 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700948 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950
Avinash Vaish71a8b972014-07-24 15:36:33 +0530951 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 status = platform_switch_voice_call_device_post(adev->platform,
953 out_snd_device,
954 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530955 enable_audio_route_for_voice_usecases(adev, usecase);
956 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800957
sangwoo170731f2013-06-08 15:36:36 +0900958 usecase->in_snd_device = in_snd_device;
959 usecase->out_snd_device = out_snd_device;
960
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530961 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700962 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530963 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700964 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530965 usecase->stream.out->flags,
966 usecase->stream.out->format,
967 usecase->stream.out->sample_rate,
968 usecase->stream.out->bit_width,
Manish Dewanganf48adb42015-05-27 10:17:41 +0530969 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530970 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700971 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700973
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900975
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800976 /* Applicable only on the targets that has external modem.
977 * Enable device command should be sent to modem only after
978 * enabling voice call mixer controls
979 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700980 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800981 status = platform_switch_voice_call_usecase_route_post(adev->platform,
982 out_snd_device,
983 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530984 ALOGD("%s: done",__func__);
985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986 return status;
987}
988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989static int stop_input_stream(struct stream_in *in)
990{
991 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 struct audio_usecase *uc_info;
993 struct audio_device *adev = in->dev;
994
Eric Laurentc8400632013-02-14 19:04:54 -0800995 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996
Eric Laurent994a6932013-07-17 11:51:42 -0700997 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 uc_info = get_usecase_from_list(adev, in->usecase);
1000 if (uc_info == NULL) {
1001 ALOGE("%s: Could not find the usecase (%d) in the list",
1002 __func__, in->usecase);
1003 return -EINVAL;
1004 }
1005
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001006 /* Close in-call recording streams */
1007 voice_check_and_stop_incall_rec_usecase(adev, in);
1008
Eric Laurent150dbfe2013-02-27 14:31:02 -08001009 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001010 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011
1012 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001013 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001015 list_remove(&uc_info->list);
1016 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017
Eric Laurent994a6932013-07-17 11:51:42 -07001018 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019 return ret;
1020}
1021
1022int start_input_stream(struct stream_in *in)
1023{
1024 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001025 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 struct audio_usecase *uc_info;
1027 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301028 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029
Mingming Yine62d7842013-10-25 16:26:03 -07001030 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301031 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1032 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001033
Naresh Tanniru80659832014-06-04 18:17:56 +05301034
1035 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301036 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301037 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301038 goto error_config;
1039 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301040
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001041 /* Check if source matches incall recording usecase criteria */
1042 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1043 if (ret)
1044 goto error_config;
1045 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001046 ALOGD("%s: Updated usecase(%d: %s)",
1047 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001048
Eric Laurentb23d5282013-05-14 15:27:20 -07001049 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 if (in->pcm_device_id < 0) {
1051 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1052 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001053 ret = -EINVAL;
1054 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056
1057 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001059
1060 if (!uc_info) {
1061 ret = -ENOMEM;
1062 goto error_config;
1063 }
1064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065 uc_info->id = in->usecase;
1066 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001067 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 uc_info->devices = in->device;
1069 uc_info->in_snd_device = SND_DEVICE_NONE;
1070 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001072 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301073 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075
Eric Laurentc8400632013-02-14 19:04:54 -08001076 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001077 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1078
1079 unsigned int flags = PCM_IN;
1080 unsigned int pcm_open_retry_count = 0;
1081
1082 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1083 flags |= PCM_MMAP | PCM_NOIRQ;
1084 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1085 }
1086
1087 while (1) {
1088 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1089 flags, &in->config);
1090 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1091 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1092 if (in->pcm != NULL) {
1093 pcm_close(in->pcm);
1094 in->pcm = NULL;
1095 }
1096 if (pcm_open_retry_count-- == 0) {
1097 ret = -EIO;
1098 goto error_open;
1099 }
1100 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1101 continue;
1102 }
1103 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301105 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301106
Eric Laurent994a6932013-07-17 11:51:42 -07001107 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001108 return ret;
1109
1110error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301112 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001113
1114error_config:
1115 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001117
1118 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119}
1120
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001121/* must be called with out->lock locked */
1122static int send_offload_cmd_l(struct stream_out* out, int command)
1123{
1124 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1125
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001126 if (!cmd) {
1127 ALOGE("failed to allocate mem for command 0x%x", command);
1128 return -ENOMEM;
1129 }
1130
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001131 ALOGVV("%s %d", __func__, command);
1132
1133 cmd->cmd = command;
1134 list_add_tail(&out->offload_cmd_list, &cmd->node);
1135 pthread_cond_signal(&out->offload_cond);
1136 return 0;
1137}
1138
1139/* must be called iwth out->lock locked */
1140static void stop_compressed_output_l(struct stream_out *out)
1141{
1142 out->offload_state = OFFLOAD_STATE_IDLE;
1143 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001144 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001145 if (out->compr != NULL) {
1146 compress_stop(out->compr);
1147 while (out->offload_thread_blocked) {
1148 pthread_cond_wait(&out->cond, &out->lock);
1149 }
1150 }
1151}
1152
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001153bool is_offload_usecase(audio_usecase_t uc_id)
1154{
1155 unsigned int i;
1156 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1157 if (uc_id == offload_usecases[i])
1158 return true;
1159 }
1160 return false;
1161}
1162
1163static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1164{
1165 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1166 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1167 char value[PROPERTY_VALUE_MAX] = {0};
1168
1169 property_get("audio.offload.multiple.enabled", value, NULL);
1170 if (!(atoi(value) || !strncmp("true", value, 4)))
1171 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1172
1173 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1174 for (i = 0; i < num_usecase; i++) {
1175 if (!(adev->offload_usecases_state & (0x1<<i))) {
1176 adev->offload_usecases_state |= 0x1 << i;
1177 ret = offload_usecases[i];
1178 break;
1179 }
1180 }
1181 ALOGV("%s: offload usecase is %d", __func__, ret);
1182 return ret;
1183}
1184
1185static void free_offload_usecase(struct audio_device *adev,
1186 audio_usecase_t uc_id)
1187{
1188 unsigned int i;
1189 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1190 if (offload_usecases[i] == uc_id) {
1191 adev->offload_usecases_state &= ~(0x1<<i);
1192 break;
1193 }
1194 }
1195 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1196}
1197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001198static void *offload_thread_loop(void *context)
1199{
1200 struct stream_out *out = (struct stream_out *) context;
1201 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001202 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001204 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1205 set_sched_policy(0, SP_FOREGROUND);
1206 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1207
1208 ALOGV("%s", __func__);
1209 pthread_mutex_lock(&out->lock);
1210 for (;;) {
1211 struct offload_cmd *cmd = NULL;
1212 stream_callback_event_t event;
1213 bool send_callback = false;
1214
1215 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1216 __func__, list_empty(&out->offload_cmd_list),
1217 out->offload_state);
1218 if (list_empty(&out->offload_cmd_list)) {
1219 ALOGV("%s SLEEPING", __func__);
1220 pthread_cond_wait(&out->offload_cond, &out->lock);
1221 ALOGV("%s RUNNING", __func__);
1222 continue;
1223 }
1224
1225 item = list_head(&out->offload_cmd_list);
1226 cmd = node_to_item(item, struct offload_cmd, node);
1227 list_remove(item);
1228
1229 ALOGVV("%s STATE %d CMD %d out->compr %p",
1230 __func__, out->offload_state, cmd->cmd, out->compr);
1231
1232 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1233 free(cmd);
1234 break;
1235 }
1236
1237 if (out->compr == NULL) {
1238 ALOGE("%s: Compress handle is NULL", __func__);
1239 pthread_cond_signal(&out->cond);
1240 continue;
1241 }
1242 out->offload_thread_blocked = true;
1243 pthread_mutex_unlock(&out->lock);
1244 send_callback = false;
1245 switch(cmd->cmd) {
1246 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001247 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001248 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001249 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001250 send_callback = true;
1251 event = STREAM_CBK_EVENT_WRITE_READY;
1252 break;
1253 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001254 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301255 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001256 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301257 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001258 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301259 if (ret < 0)
1260 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301261 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301262 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001263 compress_drain(out->compr);
1264 else
1265 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301266 if (ret != -ENETRESET) {
1267 send_callback = true;
1268 event = STREAM_CBK_EVENT_DRAIN_READY;
1269 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1270 } else
1271 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001272 break;
1273 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001274 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001276 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 send_callback = true;
1278 event = STREAM_CBK_EVENT_DRAIN_READY;
1279 break;
1280 default:
1281 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1282 break;
1283 }
1284 pthread_mutex_lock(&out->lock);
1285 out->offload_thread_blocked = false;
1286 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001287 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001288 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001290 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001291 free(cmd);
1292 }
1293
1294 pthread_cond_signal(&out->cond);
1295 while (!list_empty(&out->offload_cmd_list)) {
1296 item = list_head(&out->offload_cmd_list);
1297 list_remove(item);
1298 free(node_to_item(item, struct offload_cmd, node));
1299 }
1300 pthread_mutex_unlock(&out->lock);
1301
1302 return NULL;
1303}
1304
1305static int create_offload_callback_thread(struct stream_out *out)
1306{
1307 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1308 list_init(&out->offload_cmd_list);
1309 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1310 offload_thread_loop, out);
1311 return 0;
1312}
1313
1314static int destroy_offload_callback_thread(struct stream_out *out)
1315{
1316 pthread_mutex_lock(&out->lock);
1317 stop_compressed_output_l(out);
1318 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1319
1320 pthread_mutex_unlock(&out->lock);
1321 pthread_join(out->offload_thread, (void **) NULL);
1322 pthread_cond_destroy(&out->offload_cond);
1323
1324 return 0;
1325}
1326
Eric Laurent07eeafd2013-10-06 12:52:49 -07001327static bool allow_hdmi_channel_config(struct audio_device *adev)
1328{
1329 struct listnode *node;
1330 struct audio_usecase *usecase;
1331 bool ret = true;
1332
1333 list_for_each(node, &adev->usecase_list) {
1334 usecase = node_to_item(node, struct audio_usecase, list);
1335 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1336 /*
1337 * If voice call is already existing, do not proceed further to avoid
1338 * disabling/enabling both RX and TX devices, CSD calls, etc.
1339 * Once the voice call done, the HDMI channels can be configured to
1340 * max channels of remaining use cases.
1341 */
1342 if (usecase->id == USECASE_VOICE_CALL) {
1343 ALOGD("%s: voice call is active, no change in HDMI channels",
1344 __func__);
1345 ret = false;
1346 break;
1347 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1348 ALOGD("%s: multi channel playback is active, "
1349 "no change in HDMI channels", __func__);
1350 ret = false;
1351 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001352 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001353 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001354 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1355 ", no change in HDMI channels", __func__,
1356 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001357 ret = false;
1358 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001359 }
1360 }
1361 }
1362 return ret;
1363}
1364
1365static int check_and_set_hdmi_channels(struct audio_device *adev,
1366 unsigned int channels)
1367{
1368 struct listnode *node;
1369 struct audio_usecase *usecase;
1370
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001371 unsigned int supported_channels = platform_edid_get_max_channels(
1372 adev->platform);
1373 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001374 /* Check if change in HDMI channel config is allowed */
1375 if (!allow_hdmi_channel_config(adev))
1376 return 0;
1377
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001378 if (channels > supported_channels)
1379 channels = supported_channels;
1380
Eric Laurent07eeafd2013-10-06 12:52:49 -07001381 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001382 ALOGD("%s: Requested channels are same as current channels(%d)",
1383 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001384 return 0;
1385 }
1386
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001387 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001389 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001390 adev->cur_hdmi_channels = channels;
1391
1392 /*
1393 * Deroute all the playback streams routed to HDMI so that
1394 * the back end is deactivated. Note that backend will not
1395 * be deactivated if any one stream is connected to it.
1396 */
1397 list_for_each(node, &adev->usecase_list) {
1398 usecase = node_to_item(node, struct audio_usecase, list);
1399 if (usecase->type == PCM_PLAYBACK &&
1400 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001401 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 }
1403 }
1404
1405 /*
1406 * Enable all the streams disabled above. Now the HDMI backend
1407 * will be activated with new channel configuration
1408 */
1409 list_for_each(node, &adev->usecase_list) {
1410 usecase = node_to_item(node, struct audio_usecase, list);
1411 if (usecase->type == PCM_PLAYBACK &&
1412 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 }
1415 }
1416
1417 return 0;
1418}
1419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420static int stop_output_stream(struct stream_out *out)
1421{
1422 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 struct audio_usecase *uc_info;
1424 struct audio_device *adev = out->dev;
1425
Eric Laurent994a6932013-07-17 11:51:42 -07001426 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 uc_info = get_usecase_from_list(adev, out->usecase);
1429 if (uc_info == NULL) {
1430 ALOGE("%s: Could not find the usecase (%d) in the list",
1431 __func__, out->usecase);
1432 return -EINVAL;
1433 }
1434
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001435 if (is_offload_usecase(out->usecase) &&
1436 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001437 if (adev->visualizer_stop_output != NULL)
1438 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001439
1440 audio_extn_dts_remove_state_notifier_node(out->usecase);
1441
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001442 if (adev->offload_effects_stop_output != NULL)
1443 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1444 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001445
Eric Laurent150dbfe2013-02-27 14:31:02 -08001446 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001447 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448
1449 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001450 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001452 list_remove(&uc_info->list);
1453 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001455 if (is_offload_usecase(out->usecase) &&
1456 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1457 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1458 ALOGV("Disable passthrough , reset mixer to pcm");
1459 /* NO_PASSTHROUGH */
1460 out->compr_config.codec->compr_passthr = 0;
1461 audio_extn_dolby_set_hdmi_config(adev, out);
1462 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1463 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001464 /* Must be called after removing the usecase from list */
1465 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1466 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1467
Eric Laurent994a6932013-07-17 11:51:42 -07001468 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 return ret;
1470}
1471
1472int start_output_stream(struct stream_out *out)
1473{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001475 int sink_channels = 0;
1476 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 struct audio_usecase *uc_info;
1478 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301479 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001481 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1482 ret = -EINVAL;
1483 goto error_config;
1484 }
1485
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301486 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1487 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1488 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301489
Naresh Tanniru80659832014-06-04 18:17:56 +05301490 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301491 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301492 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301493 goto error_config;
1494 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301495
Eric Laurentb23d5282013-05-14 15:27:20 -07001496 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 if (out->pcm_device_id < 0) {
1498 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1499 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001500 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001501 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 }
1503
1504 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001505
1506 if (!uc_info) {
1507 ret = -ENOMEM;
1508 goto error_config;
1509 }
1510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 uc_info->id = out->usecase;
1512 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001513 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514 uc_info->devices = out->devices;
1515 uc_info->in_snd_device = SND_DEVICE_NONE;
1516 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001517 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001518 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001519 if (is_offload_usecase(out->usecase)) {
1520 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001521 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1522 }
1523 }
Mingming Yin9c041392014-05-01 15:37:31 -07001524 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1525 if (!strncmp("true", prop_value, 4)) {
1526 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001527 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1528 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001529 check_and_set_hdmi_channels(adev, sink_channels);
1530 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001531 if (is_offload_usecase(out->usecase)) {
1532 unsigned int ch_count = out->compr_config.codec->ch_in;
1533 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1534 /* backend channel config for passthrough stream is stereo */
1535 ch_count = 2;
1536 check_and_set_hdmi_channels(adev, ch_count);
1537 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001538 check_and_set_hdmi_channels(adev, out->config.channels);
1539 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001540 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001541 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001542 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 select_devices(adev, out->usecase);
1545
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001546 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1547 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001548 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001549 unsigned int flags = PCM_OUT;
1550 unsigned int pcm_open_retry_count = 0;
1551 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1552 flags |= PCM_MMAP | PCM_NOIRQ;
1553 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1554 } else
1555 flags |= PCM_MONOTONIC;
1556
1557 while (1) {
1558 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1559 flags, &out->config);
1560 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1561 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1562 if (out->pcm != NULL) {
1563 pcm_close(out->pcm);
1564 out->pcm = NULL;
1565 }
1566 if (pcm_open_retry_count-- == 0) {
1567 ret = -EIO;
1568 goto error_open;
1569 }
1570 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1571 continue;
1572 }
1573 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001574 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001575 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1576 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001578 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1579 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001581 out->compr = compress_open(adev->snd_card,
1582 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 COMPRESS_IN, &out->compr_config);
1584 if (out->compr && !is_compress_ready(out->compr)) {
1585 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1586 compress_close(out->compr);
1587 out->compr = NULL;
1588 ret = -EIO;
1589 goto error_open;
1590 }
1591 if (out->offload_callback)
1592 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001593
Fred Oh3f43e742015-03-04 18:42:34 -08001594 /* Since small bufs uses blocking writes, a write will be blocked
1595 for the default max poll time (20s) in the event of an SSR.
1596 Reduce the poll time to observe and deal with SSR faster.
1597 */
1598 if (out->use_small_bufs) {
1599 compress_set_max_poll_wait(out->compr, 1000);
1600 }
1601
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001602 audio_extn_dts_create_state_notifier_node(out->usecase);
1603 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1604 popcount(out->channel_mask),
1605 out->playback_started);
1606
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001607#ifdef DS1_DOLBY_DDP_ENABLED
1608 if (audio_extn_is_dolby_format(out->format))
1609 audio_extn_dolby_send_ddp_endp_params(adev);
1610#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001611 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1612 if (adev->visualizer_start_output != NULL)
1613 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1614 if (adev->offload_effects_start_output != NULL)
1615 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001616 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 }
Eric Laurent994a6932013-07-17 11:51:42 -07001619 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001621error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001623error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001624 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625}
1626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627static int check_input_parameters(uint32_t sample_rate,
1628 audio_format_t format,
1629 int channel_count)
1630{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001631 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001633 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001634 !voice_extn_compress_voip_is_format_supported(format) &&
1635 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001636
1637 switch (channel_count) {
1638 case 1:
1639 case 2:
1640 case 6:
1641 break;
1642 default:
1643 ret = -EINVAL;
1644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645
1646 switch (sample_rate) {
1647 case 8000:
1648 case 11025:
1649 case 12000:
1650 case 16000:
1651 case 22050:
1652 case 24000:
1653 case 32000:
1654 case 44100:
1655 case 48000:
1656 break;
1657 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001658 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 }
1660
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001661 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662}
1663
1664static size_t get_input_buffer_size(uint32_t sample_rate,
1665 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001666 int channel_count,
1667 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668{
1669 size_t size = 0;
1670
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001671 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1672 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001674 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001675 if (is_low_latency)
1676 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001677 /* ToDo: should use frame_size computed based on the format and
1678 channel_count here. */
1679 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001681 /* make sure the size is multiple of 32 bytes
1682 * At 48 kHz mono 16-bit PCM:
1683 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1684 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1685 */
1686 size += 0x1f;
1687 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001688
1689 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690}
1691
1692static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1693{
1694 struct stream_out *out = (struct stream_out *)stream;
1695
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697}
1698
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001699static int out_set_sample_rate(struct audio_stream *stream __unused,
1700 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701{
1702 return -ENOSYS;
1703}
1704
1705static size_t out_get_buffer_size(const struct audio_stream *stream)
1706{
1707 struct stream_out *out = (struct stream_out *)stream;
1708
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001709 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001711 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1712 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001714 return out->config.period_size *
1715 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716}
1717
1718static uint32_t out_get_channels(const struct audio_stream *stream)
1719{
1720 struct stream_out *out = (struct stream_out *)stream;
1721
1722 return out->channel_mask;
1723}
1724
1725static audio_format_t out_get_format(const struct audio_stream *stream)
1726{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727 struct stream_out *out = (struct stream_out *)stream;
1728
1729 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730}
1731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001732static int out_set_format(struct audio_stream *stream __unused,
1733 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734{
1735 return -ENOSYS;
1736}
1737
1738static int out_standby(struct audio_stream *stream)
1739{
1740 struct stream_out *out = (struct stream_out *)stream;
1741 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301743 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1744 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001745 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1746 /* Ignore standby in case of voip call because the voip output
1747 * stream is closed in adev_close_output_stream()
1748 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301749 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001750 return 0;
1751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001755 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001757 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 if (out->pcm) {
1759 pcm_close(out->pcm);
1760 out->pcm = NULL;
1761 }
1762 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001763 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001765 out->gapless_mdata.encoder_delay = 0;
1766 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 if (out->compr != NULL) {
1768 compress_close(out->compr);
1769 out->compr = NULL;
1770 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001773 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 }
1775 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001776 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 return 0;
1778}
1779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001780static int out_dump(const struct audio_stream *stream __unused,
1781 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782{
1783 return 0;
1784}
1785
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001786static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1787{
1788 int ret = 0;
1789 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001790 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001792 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001793 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001794 return -EINVAL;
1795 }
1796
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001797 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1798 if (ret >= 0) {
1799 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1800 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1801 ALOGV("ADTS format is set in offload mode");
1802 }
1803 out->send_new_metadata = 1;
1804 }
1805
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301806 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001807
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1809 if(ret >= 0)
1810 is_meta_data_params = true;
1811 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301812 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001813 is_meta_data_params = true;
1814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301815 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001816 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1818 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001819 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301820 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1823 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001824 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301825 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826 }
1827
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001828 if(!is_meta_data_params) {
1829 ALOGV("%s: Not gapless meta data params", __func__);
1830 return 0;
1831 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 out->send_new_metadata = 1;
1833 ALOGV("%s new encoder delay %u and padding %u", __func__,
1834 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1835
1836 return 0;
1837}
1838
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001839static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1840{
1841 return out == adev->primary_output || out == adev->voice_tx_output;
1842}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1845{
1846 struct stream_out *out = (struct stream_out *)stream;
1847 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001848 struct audio_usecase *usecase;
1849 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 struct str_parms *parms;
1851 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001852 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001853 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854
sangwoobc677242013-08-08 16:53:43 +09001855 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001856 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301858 if (!parms)
1859 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001860 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1861 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001864 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001866 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301867 * When HDMI cable is unplugged/usb hs is disconnected the
1868 * music playback is paused and the policy manager sends routing=0
1869 * But the audioflingercontinues to write data until standby time
1870 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871 * Avoid this by routing audio to speaker until standby.
1872 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301873 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1874 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001876 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1877 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 }
1879
1880 /*
1881 * select_devices() call below switches all the usecases on the same
1882 * backend to the new device. Refer to check_usecases_codec_backend() in
1883 * the select_devices(). But how do we undo this?
1884 *
1885 * For example, music playback is active on headset (deep-buffer usecase)
1886 * and if we go to ringtones and select a ringtone, low-latency usecase
1887 * will be started on headset+speaker. As we can't enable headset+speaker
1888 * and headset devices at the same time, select_devices() switches the music
1889 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1890 * So when the ringtone playback is completed, how do we undo the same?
1891 *
1892 * We are relying on the out_set_parameters() call on deep-buffer output,
1893 * once the ringtone playback is ended.
1894 * NOTE: We should not check if the current devices are same as new devices.
1895 * Because select_devices() must be called to switch back the music
1896 * playback to headset.
1897 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001898 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 out->devices = val;
1900
1901 if (!out->standby)
1902 select_devices(adev, out->usecase);
1903
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001904 if (output_drives_call(adev, out)) {
1905 if(!voice_is_in_call(adev)) {
1906 if (adev->mode == AUDIO_MODE_IN_CALL) {
1907 adev->current_call_output = out;
1908 ret = voice_start_call(adev);
1909 }
1910 } else {
1911 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001912 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001913 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001914 }
1915 }
1916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001918 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001920
1921 if (out == adev->primary_output) {
1922 pthread_mutex_lock(&adev->lock);
1923 audio_extn_set_parameters(adev, parms);
1924 pthread_mutex_unlock(&adev->lock);
1925 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001926 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001927 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001928 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001929
1930 audio_extn_dts_create_state_notifier_node(out->usecase);
1931 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1932 popcount(out->channel_mask),
1933 out->playback_started);
1934
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001935 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301939error:
Eric Laurent994a6932013-07-17 11:51:42 -07001940 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 return ret;
1942}
1943
1944static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1945{
1946 struct stream_out *out = (struct stream_out *)stream;
1947 struct str_parms *query = str_parms_create_str(keys);
1948 char *str;
1949 char value[256];
1950 struct str_parms *reply = str_parms_create();
1951 size_t i, j;
1952 int ret;
1953 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001954
1955 if (!query || !reply) {
1956 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1957 return NULL;
1958 }
1959
Eric Laurent994a6932013-07-17 11:51:42 -07001960 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1962 if (ret >= 0) {
1963 value[0] = '\0';
1964 i = 0;
1965 while (out->supported_channel_masks[i] != 0) {
1966 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1967 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1968 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001969 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001971 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 first = false;
1973 break;
1974 }
1975 }
1976 i++;
1977 }
1978 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1979 str = str_parms_to_str(reply);
1980 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001981 voice_extn_out_get_parameters(out, query, reply);
1982 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001983 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001984 free(str);
1985 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001988
1989 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1990 if (ret >= 0) {
1991 value[0] = '\0';
1992 i = 0;
1993 first = true;
1994 while (out->supported_formats[i] != 0) {
1995 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1996 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1997 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001998 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001999 }
2000 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2001 first = false;
2002 break;
2003 }
2004 }
2005 i++;
2006 }
2007 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2008 str = str_parms_to_str(reply);
2009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 str_parms_destroy(query);
2011 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002012 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 return str;
2014}
2015
2016static uint32_t out_get_latency(const struct audio_stream_out *stream)
2017{
2018 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002019 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020
Alexy Josephaa54c872014-12-03 02:46:47 -08002021 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002022 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002023 } else {
2024 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002025 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002026 }
2027
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302028 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002029 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030}
2031
2032static int out_set_volume(struct audio_stream_out *stream, float left,
2033 float right)
2034{
Eric Laurenta9024de2013-04-04 09:19:12 -07002035 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036 int volume[2];
2037
Eric Laurenta9024de2013-04-04 09:19:12 -07002038 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2039 /* only take left channel into account: the API is for stereo anyway */
2040 out->muted = (left == 0.0f);
2041 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002042 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002043 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2044 /*
2045 * Set mute or umute on HDMI passthrough stream.
2046 * Only take left channel into account.
2047 * Mute is 0 and unmute 1
2048 */
2049 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2050 } else {
2051 char mixer_ctl_name[128];
2052 struct audio_device *adev = out->dev;
2053 struct mixer_ctl *ctl;
2054 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002055 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002057 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2058 "Compress Playback %d Volume", pcm_device_id);
2059 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2060 if (!ctl) {
2061 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2062 __func__, mixer_ctl_name);
2063 return -EINVAL;
2064 }
2065 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2066 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2067 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2068 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002070 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 return -ENOSYS;
2073}
2074
2075static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2076 size_t bytes)
2077{
2078 struct stream_out *out = (struct stream_out *)stream;
2079 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302080 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002081 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302084
Naresh Tanniru80659832014-06-04 18:17:56 +05302085 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002086 // increase written size during SSR to avoid mismatch
2087 // with the written frames count in AF
2088 if (!is_offload_usecase(out->usecase))
2089 out->written += bytes / (out->config.channels * sizeof(short));
2090
Naresh Tanniru80659832014-06-04 18:17:56 +05302091 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302092 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302093 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302094 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002095 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302096 //during SSR for compress usecase we should return error to flinger
2097 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2098 pthread_mutex_unlock(&out->lock);
2099 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302100 }
2101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002104 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002105 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002106 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2107 ret = voice_extn_compress_voip_start_output_stream(out);
2108 else
2109 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002110 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002113 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 goto exit;
2115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002118 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002119 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002120 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002121 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002122 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2123 out->send_new_metadata = 0;
2124 }
2125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302127 if (ret < 0)
2128 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002129 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002130 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302131 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 } else if (-ENETRESET == ret) {
2134 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2135 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2136 pthread_mutex_unlock(&out->lock);
2137 out_standby(&out->stream.common);
2138 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302140 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002142 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 out->playback_started = 1;
2144 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002145
2146 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2147 popcount(out->channel_mask),
2148 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 }
2150 pthread_mutex_unlock(&out->lock);
2151 return ret;
2152 } else {
2153 if (out->pcm) {
2154 if (out->muted)
2155 memset((void *)buffer, 0, bytes);
2156 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002157 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2158 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2159 else
2160 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302161 if (ret < 0)
2162 ret = -errno;
2163 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002164 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167
2168exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302169 /* ToDo: There may be a corner case when SSR happens back to back during
2170 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302171 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302172 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302173 }
2174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 pthread_mutex_unlock(&out->lock);
2176
2177 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002178 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002179 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302180 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302181 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302182 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302183 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302184 out->standby = true;
2185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002187 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302188 out_get_sample_rate(&out->stream.common));
2189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 }
2191 return bytes;
2192}
2193
2194static int out_get_render_position(const struct audio_stream_out *stream,
2195 uint32_t *dsp_frames)
2196{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302198 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002199
2200 if (dsp_frames == NULL)
2201 return -EINVAL;
2202
2203 *dsp_frames = 0;
2204 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002205 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 pthread_mutex_lock(&out->lock);
2207 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302208 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302210 if (ret < 0)
2211 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212 ALOGVV("%s rendered frames %d sample_rate %d",
2213 __func__, *dsp_frames, out->sample_rate);
2214 }
2215 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302216 if (-ENETRESET == ret) {
2217 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2218 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2219 return -EINVAL;
2220 } else if(ret < 0) {
2221 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2222 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302223 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2224 /*
2225 * Handle corner case where compress session is closed during SSR
2226 * and timestamp is queried
2227 */
2228 ALOGE(" ERROR: sound card not active, return error");
2229 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302230 } else {
2231 return 0;
2232 }
Zhou Song32a556e2015-05-05 10:46:56 +08002233 } else if (audio_is_linear_pcm(out->format)) {
2234 *dsp_frames = out->written;
2235 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 } else
2237 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238}
2239
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002240static int out_add_audio_effect(const struct audio_stream *stream __unused,
2241 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242{
2243 return 0;
2244}
2245
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002246static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2247 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248{
2249 return 0;
2250}
2251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002252static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2253 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return -EINVAL;
2256}
2257
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002258static int out_get_presentation_position(const struct audio_stream_out *stream,
2259 uint64_t *frames, struct timespec *timestamp)
2260{
2261 struct stream_out *out = (struct stream_out *)stream;
2262 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002263 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002264
2265 pthread_mutex_lock(&out->lock);
2266
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002267 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002268 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302269 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002270 &out->sample_rate);
2271 ALOGVV("%s rendered frames %ld sample_rate %d",
2272 __func__, dsp_frames, out->sample_rate);
2273 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302274 if (ret < 0)
2275 ret = -errno;
2276 if (-ENETRESET == ret) {
2277 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2278 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2279 ret = -EINVAL;
2280 } else
2281 ret = 0;
2282
Eric Laurent949a0892013-09-20 09:20:13 -07002283 /* this is the best we can do */
2284 clock_gettime(CLOCK_MONOTONIC, timestamp);
2285 }
2286 } else {
2287 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002288 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002289 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2290 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002291 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002292 // This adjustment accounts for buffering after app processor.
2293 // It is based on estimated DSP latency per use case, rather than exact.
2294 signed_frames -=
2295 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2296
Eric Laurent949a0892013-09-20 09:20:13 -07002297 // It would be unusual for this value to be negative, but check just in case ...
2298 if (signed_frames >= 0) {
2299 *frames = signed_frames;
2300 ret = 0;
2301 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002302 }
2303 }
2304 }
2305
2306 pthread_mutex_unlock(&out->lock);
2307
2308 return ret;
2309}
2310
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002311static int out_set_callback(struct audio_stream_out *stream,
2312 stream_callback_t callback, void *cookie)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315
2316 ALOGV("%s", __func__);
2317 pthread_mutex_lock(&out->lock);
2318 out->offload_callback = callback;
2319 out->offload_cookie = cookie;
2320 pthread_mutex_unlock(&out->lock);
2321 return 0;
2322}
2323
2324static int out_pause(struct audio_stream_out* stream)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327 int status = -ENOSYS;
2328 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002329 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002330 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 pthread_mutex_lock(&out->lock);
2332 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302333 struct audio_device *adev = out->dev;
2334 int snd_scard_state = get_snd_card_state(adev);
2335
2336 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2337 status = compress_pause(out->compr);
2338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002340
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302341 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002342 audio_extn_dts_notify_playback_state(out->usecase, 0,
2343 out->sample_rate, popcount(out->channel_mask),
2344 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 }
2346 pthread_mutex_unlock(&out->lock);
2347 }
2348 return status;
2349}
2350
2351static int out_resume(struct audio_stream_out* stream)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354 int status = -ENOSYS;
2355 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002356 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002357 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 status = 0;
2359 pthread_mutex_lock(&out->lock);
2360 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302361 struct audio_device *adev = out->dev;
2362 int snd_scard_state = get_snd_card_state(adev);
2363
2364 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2365 status = compress_resume(out->compr);
2366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002368
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302369 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002370 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2371 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 }
2373 pthread_mutex_unlock(&out->lock);
2374 }
2375 return status;
2376}
2377
2378static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2379{
2380 struct stream_out *out = (struct stream_out *)stream;
2381 int status = -ENOSYS;
2382 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002383 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 pthread_mutex_lock(&out->lock);
2385 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2386 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2387 else
2388 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2389 pthread_mutex_unlock(&out->lock);
2390 }
2391 return status;
2392}
2393
2394static int out_flush(struct audio_stream_out* stream)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002398 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002399 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 pthread_mutex_lock(&out->lock);
2401 stop_compressed_output_l(out);
2402 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002403 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 return 0;
2405 }
2406 return -ENOSYS;
2407}
2408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409/** audio_stream_in implementation **/
2410static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2411{
2412 struct stream_in *in = (struct stream_in *)stream;
2413
2414 return in->config.rate;
2415}
2416
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002417static int in_set_sample_rate(struct audio_stream *stream __unused,
2418 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419{
2420 return -ENOSYS;
2421}
2422
2423static size_t in_get_buffer_size(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002427 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2428 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002429 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2430 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002431
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002432 return in->config.period_size *
2433 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434}
2435
2436static uint32_t in_get_channels(const struct audio_stream *stream)
2437{
2438 struct stream_in *in = (struct stream_in *)stream;
2439
2440 return in->channel_mask;
2441}
2442
2443static audio_format_t in_get_format(const struct audio_stream *stream)
2444{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002445 struct stream_in *in = (struct stream_in *)stream;
2446
2447 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448}
2449
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002450static int in_set_format(struct audio_stream *stream __unused,
2451 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452{
2453 return -ENOSYS;
2454}
2455
2456static int in_standby(struct audio_stream *stream)
2457{
2458 struct stream_in *in = (struct stream_in *)stream;
2459 struct audio_device *adev = in->dev;
2460 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302461 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2462 stream, in->usecase, use_case_table[in->usecase]);
2463
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002464 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2465 /* Ignore standby in case of voip call because the voip input
2466 * stream is closed in adev_close_input_stream()
2467 */
2468 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2469 return status;
2470 }
2471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002473 if (!in->standby && in->is_st_session) {
2474 ALOGD("%s: sound trigger pcm stop lab", __func__);
2475 audio_extn_sound_trigger_stop_lab(in);
2476 in->standby = 1;
2477 }
2478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002480 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002482 if (in->pcm) {
2483 pcm_close(in->pcm);
2484 in->pcm = NULL;
2485 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002487 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 }
2489 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002490 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 return status;
2492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int in_dump(const struct audio_stream *stream __unused,
2495 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return 0;
2498}
2499
2500static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2501{
2502 struct stream_in *in = (struct stream_in *)stream;
2503 struct audio_device *adev = in->dev;
2504 struct str_parms *parms;
2505 char *str;
2506 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002507 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302509 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 parms = str_parms_create_str(kvpairs);
2511
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302512 if (!parms)
2513 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002515 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002516
2517 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2518 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 val = atoi(value);
2520 /* no audio source uses val == 0 */
2521 if ((in->source != val) && (val != 0)) {
2522 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002523 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2524 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2525 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2526 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002527 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002528 err = voice_extn_compress_voip_open_input_stream(in);
2529 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002530 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002531 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002532 }
2533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 }
2535 }
2536
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002537 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2538 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002540 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 in->device = val;
2542 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002543 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002544 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 }
2546 }
2547
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002548done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002550 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551
2552 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302553error:
Eric Laurent994a6932013-07-17 11:51:42 -07002554 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 return ret;
2556}
2557
2558static char* in_get_parameters(const struct audio_stream *stream,
2559 const char *keys)
2560{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561 struct stream_in *in = (struct stream_in *)stream;
2562 struct str_parms *query = str_parms_create_str(keys);
2563 char *str;
2564 char value[256];
2565 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002566
2567 if (!query || !reply) {
2568 ALOGE("in_get_parameters: failed to create query or reply");
2569 return NULL;
2570 }
2571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002572 ALOGV("%s: enter: keys - %s", __func__, keys);
2573
2574 voice_extn_in_get_parameters(in, query, reply);
2575
2576 str = str_parms_to_str(reply);
2577 str_parms_destroy(query);
2578 str_parms_destroy(reply);
2579
2580 ALOGV("%s: exit: returns - %s", __func__, str);
2581 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002584static int in_set_gain(struct audio_stream_in *stream __unused,
2585 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586{
2587 return 0;
2588}
2589
2590static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2591 size_t bytes)
2592{
2593 struct stream_in *in = (struct stream_in *)stream;
2594 struct audio_device *adev = in->dev;
2595 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302596 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302599
2600 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302601 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302602 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302603 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302604 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002605 } else {
2606 if (in->is_st_session && !in->is_st_session_active) {
2607 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2608 ret= -EIO;;
2609 goto exit;
2610 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302611 }
2612 }
2613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002615 if (!in->is_st_session) {
2616 pthread_mutex_lock(&adev->lock);
2617 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2618 ret = voice_extn_compress_voip_start_input_stream(in);
2619 else
2620 ret = start_input_stream(in);
2621 pthread_mutex_unlock(&adev->lock);
2622 if (ret != 0) {
2623 goto exit;
2624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 }
2626 in->standby = 0;
2627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
2629 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002630 if (audio_extn_ssr_get_enabled() &&
2631 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002632 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002633 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2634 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002635 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2636 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002637 else
2638 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302639 if (ret < 0)
2640 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 }
2642
2643 /*
2644 * Instead of writing zeroes here, we could trust the hardware
2645 * to always provide zeroes when muted.
2646 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302647 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2648 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 memset(buffer, 0, bytes);
2650
2651exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302652 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302653 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302654 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002655 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2656 session reading on LAB data. In this case do not set sound card state
2657 offline, instead mark this sound trigger session inactive to avoid
2658 further reading of LAB data from CPE driver. Marking the session
2659 inactive handles both CPE and ADSP SSR for sound trigger session */
2660 if (!in->is_st_session)
2661 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2662 else
2663 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 pthread_mutex_unlock(&in->lock);
2666
2667 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302668 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302669 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302670 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302671 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302672 in->standby = true;
2673 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302674 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002676 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002677 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302678 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 }
2680 return bytes;
2681}
2682
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002683static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684{
2685 return 0;
2686}
2687
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002688static int add_remove_audio_effect(const struct audio_stream *stream,
2689 effect_handle_t effect,
2690 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002692 struct stream_in *in = (struct stream_in *)stream;
2693 int status = 0;
2694 effect_descriptor_t desc;
2695
2696 status = (*effect)->get_descriptor(effect, &desc);
2697 if (status != 0)
2698 return status;
2699
2700 pthread_mutex_lock(&in->lock);
2701 pthread_mutex_lock(&in->dev->lock);
2702 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2703 in->enable_aec != enable &&
2704 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2705 in->enable_aec = enable;
2706 if (!in->standby)
2707 select_devices(in->dev, in->usecase);
2708 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002709 if (in->enable_ns != enable &&
2710 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2711 in->enable_ns = enable;
2712 if (!in->standby)
2713 select_devices(in->dev, in->usecase);
2714 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002715 pthread_mutex_unlock(&in->dev->lock);
2716 pthread_mutex_unlock(&in->lock);
2717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 return 0;
2719}
2720
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002721static int in_add_audio_effect(const struct audio_stream *stream,
2722 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
Eric Laurent994a6932013-07-17 11:51:42 -07002724 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002725 return add_remove_audio_effect(stream, effect, true);
2726}
2727
2728static int in_remove_audio_effect(const struct audio_stream *stream,
2729 effect_handle_t effect)
2730{
Eric Laurent994a6932013-07-17 11:51:42 -07002731 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002732 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733}
2734
2735static int adev_open_output_stream(struct audio_hw_device *dev,
2736 audio_io_handle_t handle,
2737 audio_devices_t devices,
2738 audio_output_flags_t flags,
2739 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002740 struct audio_stream_out **stream_out,
2741 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742{
2743 struct audio_device *adev = (struct audio_device *)dev;
2744 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002745 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002746 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302749
2750 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2751 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2752 ALOGE(" sound card is not active rejecting compress output open request");
2753 return -EINVAL;
2754 }
2755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2757
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302758 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2759 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2760 devices, flags, &out->stream);
2761
2762
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002763 if (!out) {
2764 return -ENOMEM;
2765 }
2766
Haynes Mathew George204045b2015-02-25 20:32:03 -08002767 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2768 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 if (devices == AUDIO_DEVICE_NONE)
2771 devices = AUDIO_DEVICE_OUT_SPEAKER;
2772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 out->flags = flags;
2774 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002775 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002776 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 out->sample_rate = config->sample_rate;
2778 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2779 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002780 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002781 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002782 out->non_blocking = 0;
2783 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784
2785 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002786 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2787 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2788 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2789
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002790 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002791 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2792 ret = read_hdmi_channel_masks(out);
2793
2794 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2795 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002796 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002797 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002798 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799
2800 if (config->sample_rate == 0)
2801 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2802 if (config->channel_mask == 0)
2803 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2804
2805 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2808 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002810 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002812 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2813 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002814 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002815 ret = voice_extn_compress_voip_open_output_stream(out);
2816 if (ret != 0) {
2817 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2818 __func__, ret);
2819 goto error_open;
2820 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2822 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2823 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2824 ALOGE("%s: Unsupported Offload information", __func__);
2825 ret = -EINVAL;
2826 goto error_open;
2827 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002828
2829 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2830 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2831 ALOGV("read and update_pass through formats");
2832 ret = audio_extn_dolby_update_passt_formats(adev, out);
2833 if(ret != 0) {
2834 goto error_open;
2835 }
2836 if(config->offload_info.format == 0)
2837 config->offload_info.format = out->supported_formats[0];
2838 }
2839
Mingming Yin90310102013-11-13 16:57:00 -08002840 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002841 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 ALOGE("%s: Unsupported audio format", __func__);
2843 ret = -EINVAL;
2844 goto error_open;
2845 }
2846
2847 out->compr_config.codec = (struct snd_codec *)
2848 calloc(1, sizeof(struct snd_codec));
2849
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002850 if (!out->compr_config.codec) {
2851 ret = -ENOMEM;
2852 goto error_open;
2853 }
2854
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002855 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 if (config->offload_info.channel_mask)
2857 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002858 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002860 config->offload_info.channel_mask = config->channel_mask;
2861 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002862 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 out->sample_rate = config->offload_info.sample_rate;
2864
2865 out->stream.set_callback = out_set_callback;
2866 out->stream.pause = out_pause;
2867 out->stream.resume = out_resume;
2868 out->stream.drain = out_drain;
2869 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002870 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002872 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002873 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002874 audio_extn_dolby_get_snd_codec_id(adev, out,
2875 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002876 else
2877 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002879 if (audio_is_offload_pcm(config->offload_info.format)) {
2880 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002881 platform_get_pcm_offload_buffer_size(&config->offload_info);
2882 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2883 out->compr_config.fragment_size =
2884 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002885 } else {
2886 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002887 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002888 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2890 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302891 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->compr_config.codec->bit_rate =
2893 config->offload_info.bit_rate;
2894 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002895 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002897 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002898 /*TODO: Do we need to change it for passthrough */
2899 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900
Mingming Yin3ee55c62014-08-04 14:23:35 -07002901 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2902 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002903 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2904 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002905 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2907
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 if (out->bit_width == 24) {
2909 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2910 }
2911
Amit Shekhar6f461b12014-08-01 14:52:58 -07002912 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002913 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2916 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002917
Alexy Josephaa54c872014-12-03 02:46:47 -08002918 if (config->offload_info.use_small_bufs) {
2919 //this flag is set from framework only if its for PCM formats
2920 //no need to check for PCM format again
2921 out->non_blocking = 0;
2922 out->use_small_bufs = true;
2923 ALOGI("Keep write blocking for small buff: non_blockling %d",
2924 out->non_blocking);
2925 }
2926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002927 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002928 out->offload_state = OFFLOAD_STATE_IDLE;
2929 out->playback_started = 0;
2930
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002931 audio_extn_dts_create_state_notifier_node(out->usecase);
2932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 create_offload_callback_thread(out);
2934 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2935 __func__, config->offload_info.version,
2936 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002937 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002938 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002939 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2940 ret = voice_check_and_set_incall_music_usecase(adev, out);
2941 if (ret != 0) {
2942 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2943 __func__, ret);
2944 goto error_open;
2945 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002946 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2947 if (config->sample_rate == 0)
2948 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2949 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2950 config->sample_rate != 8000) {
2951 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2952 ret = -EINVAL;
2953 goto error_open;
2954 }
2955 out->sample_rate = config->sample_rate;
2956 out->config.rate = config->sample_rate;
2957 if (config->format == AUDIO_FORMAT_DEFAULT)
2958 config->format = AUDIO_FORMAT_PCM_16_BIT;
2959 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2960 config->format = AUDIO_FORMAT_PCM_16_BIT;
2961 ret = -EINVAL;
2962 goto error_open;
2963 }
2964 out->format = config->format;
2965 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2966 out->config = pcm_config_afe_proxy_playback;
2967 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002968 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002969 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2971 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002972 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002973 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2974 format = AUDIO_FORMAT_PCM_16_BIT;
2975 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2976 out->config = pcm_config_deep_buffer;
2977 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002978 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002979 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002980 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002981 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002982 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002983 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 }
2985
Amit Shekhar1d896042014-10-03 13:16:09 -07002986 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2987 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002988 /* TODO remove this hardcoding and check why width is zero*/
2989 if (out->bit_width == 0)
2990 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002991 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2992 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002993 devices, flags, format, out->sample_rate,
Manish Dewanganf48adb42015-05-27 10:17:41 +05302994 out->bit_width, out->channel_mask,
2995 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002996 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2997 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2998 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002999 if(adev->primary_output == NULL)
3000 adev->primary_output = out;
3001 else {
3002 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003003 ret = -EEXIST;
3004 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003005 }
3006 }
3007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 /* Check if this usecase is already existing */
3009 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003010 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3011 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003014 ret = -EEXIST;
3015 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 }
3017 pthread_mutex_unlock(&adev->lock);
3018
3019 out->stream.common.get_sample_rate = out_get_sample_rate;
3020 out->stream.common.set_sample_rate = out_set_sample_rate;
3021 out->stream.common.get_buffer_size = out_get_buffer_size;
3022 out->stream.common.get_channels = out_get_channels;
3023 out->stream.common.get_format = out_get_format;
3024 out->stream.common.set_format = out_set_format;
3025 out->stream.common.standby = out_standby;
3026 out->stream.common.dump = out_dump;
3027 out->stream.common.set_parameters = out_set_parameters;
3028 out->stream.common.get_parameters = out_get_parameters;
3029 out->stream.common.add_audio_effect = out_add_audio_effect;
3030 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3031 out->stream.get_latency = out_get_latency;
3032 out->stream.set_volume = out_set_volume;
3033 out->stream.write = out_write;
3034 out->stream.get_render_position = out_get_render_position;
3035 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003036 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003039 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003040 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041
3042 config->format = out->stream.common.get_format(&out->stream.common);
3043 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3044 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3045
3046 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303047 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3048 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003049
3050 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3051 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3052 popcount(out->channel_mask), out->playback_started);
3053
Eric Laurent994a6932013-07-17 11:51:42 -07003054 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003056
3057error_open:
3058 free(out);
3059 *stream_out = NULL;
3060 ALOGD("%s: exit: ret %d", __func__, ret);
3061 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062}
3063
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003064static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 struct audio_stream_out *stream)
3066{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 struct stream_out *out = (struct stream_out *)stream;
3068 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303071 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3072
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303074 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303076 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003077 if(ret != 0)
3078 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3079 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003080 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 out_standby(&stream->common);
3082
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003083 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003084 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003086 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 if (out->compr_config.codec != NULL)
3088 free(out->compr_config.codec);
3089 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003090
3091 if (adev->voice_tx_output == out)
3092 adev->voice_tx_output = NULL;
3093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 pthread_cond_destroy(&out->cond);
3095 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003097 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003100static void close_compress_sessions(struct audio_device *adev)
3101{
Mingming Yin7b762e72015-03-04 13:47:32 -08003102 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303103 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003104 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003105 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303106
3107 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003108 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303109 if (is_offload_usecase(usecase->id)) {
3110 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003111 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3112 out = usecase->stream.out;
3113 pthread_mutex_unlock(&adev->lock);
3114 out_standby(&out->stream.common);
3115 pthread_mutex_lock(&adev->lock);
3116 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303117 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003118 }
3119 pthread_mutex_unlock(&adev->lock);
3120}
3121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3123{
3124 struct audio_device *adev = (struct audio_device *)dev;
3125 struct str_parms *parms;
3126 char *str;
3127 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003128 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003129 int ret;
3130 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003132 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303135 if (!parms)
3136 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003137 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3138 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303139 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303140 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303141 struct listnode *node;
3142 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303144 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003145 //close compress sessions on OFFLINE status
3146 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303147 } else if (strstr(snd_card_status, "ONLINE")) {
3148 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303149 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 }
3152
3153 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 status = voice_set_parameters(adev, parms);
3155 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003156 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 status = platform_set_parameters(adev->platform, parms);
3159 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003160 goto done;
3161
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3163 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003164 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3166 adev->bluetooth_nrec = true;
3167 else
3168 adev->bluetooth_nrec = false;
3169 }
3170
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3172 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3174 adev->screen_off = false;
3175 else
3176 adev->screen_off = true;
3177 }
3178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_int(parms, "rotation", &val);
3180 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 bool reverse_speakers = false;
3182 switch(val) {
3183 // FIXME: note that the code below assumes that the speakers are in the correct placement
3184 // relative to the user when the device is rotated 90deg from its default rotation. This
3185 // assumption is device-specific, not platform-specific like this code.
3186 case 270:
3187 reverse_speakers = true;
3188 break;
3189 case 0:
3190 case 90:
3191 case 180:
3192 break;
3193 default:
3194 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003196 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 if (status == 0) {
3198 if (adev->speaker_lr_swap != reverse_speakers) {
3199 adev->speaker_lr_swap = reverse_speakers;
3200 // only update the selected device if there is active pcm playback
3201 struct audio_usecase *usecase;
3202 struct listnode *node;
3203 list_for_each(node, &adev->usecase_list) {
3204 usecase = node_to_item(node, struct audio_usecase, list);
3205 if (usecase->type == PCM_PLAYBACK) {
3206 select_devices(adev, usecase->id);
3207 break;
3208 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003209 }
3210 }
3211 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003212 }
3213
Mingming Yin514a8bc2014-07-29 15:22:21 -07003214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3215 if (ret >= 0) {
3216 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3217 adev->bt_wb_speech_enabled = true;
3218 else
3219 adev->bt_wb_speech_enabled = false;
3220 }
3221
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003222 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3223 if (ret >= 0) {
3224 val = atoi(value);
3225 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3226 ALOGV("cache new edid");
3227 platform_cache_edid(adev->platform);
3228 }
3229 }
3230
3231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3232 if (ret >= 0) {
3233 val = atoi(value);
3234 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3235 ALOGV("invalidate cached edid");
3236 platform_invalidate_edid(adev->platform);
3237 }
3238 }
3239
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003240 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003241
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003242done:
3243 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003244 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303245error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003246 ALOGV("%s: exit with code(%d)", __func__, status);
3247 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
3250static char* adev_get_parameters(const struct audio_hw_device *dev,
3251 const char *keys)
3252{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003253 struct audio_device *adev = (struct audio_device *)dev;
3254 struct str_parms *reply = str_parms_create();
3255 struct str_parms *query = str_parms_create_str(keys);
3256 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303257 char value[256] = {0};
3258 int ret = 0;
3259
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003260 if (!query || !reply) {
3261 ALOGE("adev_get_parameters: failed to create query or reply");
3262 return NULL;
3263 }
3264
Naresh Tannirud7205b62014-06-20 02:54:48 +05303265 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3266 sizeof(value));
3267 if (ret >=0) {
3268 int val = 1;
3269 pthread_mutex_lock(&adev->snd_card_status.lock);
3270 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3271 val = 0;
3272 pthread_mutex_unlock(&adev->snd_card_status.lock);
3273 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3274 goto exit;
3275 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003276
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003277 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003278 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003279 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003280 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303281 pthread_mutex_unlock(&adev->lock);
3282
Naresh Tannirud7205b62014-06-20 02:54:48 +05303283exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003284 str = str_parms_to_str(reply);
3285 str_parms_destroy(query);
3286 str_parms_destroy(reply);
3287
3288 ALOGV("%s: exit: returns - %s", __func__, str);
3289 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290}
3291
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003292static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return 0;
3295}
3296
3297static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3298{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003299 int ret;
3300 struct audio_device *adev = (struct audio_device *)dev;
3301 pthread_mutex_lock(&adev->lock);
3302 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003303 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003304 pthread_mutex_unlock(&adev->lock);
3305 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3309 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -ENOSYS;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3315 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3321 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3327 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
3332static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3333{
3334 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 pthread_mutex_lock(&adev->lock);
3337 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003338 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003340 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3341 voice_is_in_call(adev)) {
3342 voice_stop_call(adev);
3343 adev->current_call_output = NULL;
3344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 }
3346 pthread_mutex_unlock(&adev->lock);
3347 return 0;
3348}
3349
3350static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3351{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003352 int ret;
3353
3354 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003355 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003356 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3357 pthread_mutex_unlock(&adev->lock);
3358
3359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
3362static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3363{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003364 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 return 0;
3366}
3367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003368static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 const struct audio_config *config)
3370{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003373 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3374 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
3377static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003378 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 audio_devices_t devices,
3380 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003381 struct audio_stream_in **stream_in,
3382 audio_input_flags_t flags __unused,
3383 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003384 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
3386 struct audio_device *adev = (struct audio_device *)dev;
3387 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003388 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003390 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 *stream_in = NULL;
3393 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3394 return -EINVAL;
3395
3396 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003397
3398 if (!in) {
3399 ALOGE("failed to allocate input stream");
3400 return -ENOMEM;
3401 }
3402
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003404 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3405 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003407 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 in->stream.common.get_sample_rate = in_get_sample_rate;
3410 in->stream.common.set_sample_rate = in_set_sample_rate;
3411 in->stream.common.get_buffer_size = in_get_buffer_size;
3412 in->stream.common.get_channels = in_get_channels;
3413 in->stream.common.get_format = in_get_format;
3414 in->stream.common.set_format = in_set_format;
3415 in->stream.common.standby = in_standby;
3416 in->stream.common.dump = in_dump;
3417 in->stream.common.set_parameters = in_set_parameters;
3418 in->stream.common.get_parameters = in_get_parameters;
3419 in->stream.common.add_audio_effect = in_add_audio_effect;
3420 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3421 in->stream.set_gain = in_set_gain;
3422 in->stream.read = in_read;
3423 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3424
3425 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->standby = 1;
3429 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003430 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
3432 /* Update config params with the requested sample rate and channels */
3433 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003434 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3435 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3436 is_low_latency = true;
3437#if LOW_LATENCY_CAPTURE_USE_CASE
3438 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3439#endif
3440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003443 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003445 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303446 if (adev->mode != AUDIO_MODE_IN_CALL) {
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003450 if (config->sample_rate == 0)
3451 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3452 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3453 config->sample_rate != 8000) {
3454 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3455 ret = -EINVAL;
3456 goto err_open;
3457 }
3458 if (config->format == AUDIO_FORMAT_DEFAULT)
3459 config->format = AUDIO_FORMAT_PCM_16_BIT;
3460 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3461 config->format = AUDIO_FORMAT_PCM_16_BIT;
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465
3466 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3467 in->config = pcm_config_afe_proxy_record;
3468 in->config.channels = channel_count;
3469 in->config.rate = config->sample_rate;
3470 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003471 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003472 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003473 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003478 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 }
Mingming Yine62d7842013-10-25 16:26:03 -07003480 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003481 audio_extn_compr_cap_format_supported(config->format) &&
3482 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 } else {
3485 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003486 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003487 buffer_size = get_input_buffer_size(config->sample_rate,
3488 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003489 channel_count,
3490 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003491 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003492 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3493 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3494 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3495 (in->config.rate == 8000 || in->config.rate == 16000) &&
3496 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3497 voice_extn_compress_voip_open_input_stream(in);
3498 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003501 /* This stream could be for sound trigger lab,
3502 get sound trigger pcm if present */
3503 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303504 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003507 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003508 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
3510err_open:
3511 free(in);
3512 *stream_in = NULL;
3513 return ret;
3514}
3515
3516static void adev_close_input_stream(struct audio_hw_device *dev,
3517 struct audio_stream_in *stream)
3518{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003519 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003521 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303523 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003524
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303525 /* Disable echo reference while closing input stream */
3526 platform_set_echo_reference(adev->platform, false);
3527
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003528 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303529 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303531 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003532 if (ret != 0)
3533 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3534 __func__, ret);
3535 } else
3536 in_standby(&stream->common);
3537
Mingming Yin7b762e72015-03-04 13:47:32 -08003538 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003539 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 audio_extn_ssr_deinit();
3541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Mingming Yine62d7842013-10-25 16:26:03 -07003543 if(audio_extn_compr_cap_enabled() &&
3544 audio_extn_compr_cap_format_supported(in->config.format))
3545 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003546
3547 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 return;
3549}
3550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003551static int adev_dump(const audio_hw_device_t *device __unused,
3552 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
3554 return 0;
3555}
3556
3557static int adev_close(hw_device_t *device)
3558{
3559 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003560
3561 if (!adev)
3562 return 0;
3563
3564 pthread_mutex_lock(&adev_init_lock);
3565
3566 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003567 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003568 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003570 audio_route_free(adev->audio_route);
3571 free(adev->snd_dev_ref_cnt);
3572 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003573 free(device);
3574 adev = NULL;
3575 }
3576 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 return 0;
3578}
3579
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003580/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3581 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3582 * just that it _might_ work.
3583 */
3584static int period_size_is_plausible_for_low_latency(int period_size)
3585{
3586 switch (period_size) {
3587 case 160:
3588 case 240:
3589 case 320:
3590 case 480:
3591 return 1;
3592 default:
3593 return 0;
3594 }
3595}
3596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597static int adev_open(const hw_module_t *module, const char *name,
3598 hw_device_t **device)
3599{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003600 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003602 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3604
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003605 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003606 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003607 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003608 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003609 ALOGD("%s: returning existing instance of adev", __func__);
3610 ALOGD("%s: exit", __func__);
3611 pthread_mutex_unlock(&adev_init_lock);
3612 return 0;
3613 }
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 adev = calloc(1, sizeof(struct audio_device));
3616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003617 if (!adev) {
3618 pthread_mutex_unlock(&adev_init_lock);
3619 return -ENOMEM;
3620 }
3621
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003622 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3625 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3626 adev->device.common.module = (struct hw_module_t *)module;
3627 adev->device.common.close = adev_close;
3628
3629 adev->device.init_check = adev_init_check;
3630 adev->device.set_voice_volume = adev_set_voice_volume;
3631 adev->device.set_master_volume = adev_set_master_volume;
3632 adev->device.get_master_volume = adev_get_master_volume;
3633 adev->device.set_master_mute = adev_set_master_mute;
3634 adev->device.get_master_mute = adev_get_master_mute;
3635 adev->device.set_mode = adev_set_mode;
3636 adev->device.set_mic_mute = adev_set_mic_mute;
3637 adev->device.get_mic_mute = adev_get_mic_mute;
3638 adev->device.set_parameters = adev_set_parameters;
3639 adev->device.get_parameters = adev_get_parameters;
3640 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3641 adev->device.open_output_stream = adev_open_output_stream;
3642 adev->device.close_output_stream = adev_close_output_stream;
3643 adev->device.open_input_stream = adev_open_input_stream;
3644 adev->device.close_input_stream = adev_close_input_stream;
3645 adev->device.dump = adev_dump;
3646
3647 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003649 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003650 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003653 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003654 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003655 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003656 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003657 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003658 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003659 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303660
3661 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3662 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003664 adev->platform = platform_init(adev);
3665 if (!adev->platform) {
3666 free(adev->snd_dev_ref_cnt);
3667 free(adev);
3668 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3669 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003670 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003671 return -EINVAL;
3672 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003673
Naresh Tanniru4c630392014-05-12 01:05:52 +05303674 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3675
Eric Laurentc4aef752013-09-12 17:45:53 -07003676 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3677 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3678 if (adev->visualizer_lib == NULL) {
3679 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3680 } else {
3681 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3682 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 "visualizer_hal_start_output");
3685 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003687 "visualizer_hal_stop_output");
3688 }
3689 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003690 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003691 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003692
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003693 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3694 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3695 if (adev->offload_effects_lib == NULL) {
3696 ALOGE("%s: DLOPEN failed for %s", __func__,
3697 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3698 } else {
3699 ALOGV("%s: DLOPEN successful for %s", __func__,
3700 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3701 adev->offload_effects_start_output =
3702 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3703 "offload_effects_bundle_hal_start_output");
3704 adev->offload_effects_stop_output =
3705 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3706 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003707 adev->offload_effects_set_hpx_state =
3708 (int (*)(bool))dlsym(adev->offload_effects_lib,
3709 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003710 }
3711 }
3712
Mingming Yin514a8bc2014-07-29 15:22:21 -07003713 adev->bt_wb_speech_enabled = false;
3714
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003715 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 *device = &adev->device.common;
3717
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003718 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3719 &adev->streams_output_cfg_list);
3720
Kiran Kandi910e1862013-10-29 13:29:42 -07003721 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003722
3723 char value[PROPERTY_VALUE_MAX];
3724 int trial;
3725 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3726 trial = atoi(value);
3727 if (period_size_is_plausible_for_low_latency(trial)) {
3728 pcm_config_low_latency.period_size = trial;
3729 pcm_config_low_latency.start_threshold = trial / 4;
3730 pcm_config_low_latency.avail_min = trial / 4;
3731 configured_low_latency_capture_period_size = trial;
3732 }
3733 }
3734 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3735 trial = atoi(value);
3736 if (period_size_is_plausible_for_low_latency(trial)) {
3737 configured_low_latency_capture_period_size = trial;
3738 }
3739 }
3740
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003741 pthread_mutex_unlock(&adev_init_lock);
3742
Eric Laurent994a6932013-07-17 11:51:42 -07003743 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 return 0;
3745}
3746
3747static struct hw_module_methods_t hal_module_methods = {
3748 .open = adev_open,
3749};
3750
3751struct audio_module HAL_MODULE_INFO_SYM = {
3752 .common = {
3753 .tag = HARDWARE_MODULE_TAG,
3754 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3755 .hal_api_version = HARDWARE_HAL_API_VERSION,
3756 .id = AUDIO_HARDWARE_MODULE_ID,
3757 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003758 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 .methods = &hal_module_methods,
3760 },
3761};