blob: 197bdfb615b11513cb0f692c7ef6457737551f69 [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);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
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);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
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
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Linux Build Service Account75e43952015-08-26 19:58:56 -0700572 if (snd_device == SND_DEVICE_OUT_HDMI)
573 adev->mChannelStatusSet = false;
574
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200575 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700576 audio_extn_sound_trigger_update_device_status(snd_device,
577 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530578 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800579 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 return 0;
583}
584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585static void check_usecases_codec_backend(struct audio_device *adev,
586 struct audio_usecase *uc_info,
587 snd_device_t snd_device)
588{
589 struct listnode *node;
590 struct audio_usecase *usecase;
591 bool switch_device[AUDIO_USECASE_MAX];
592 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530593 int backend_idx = DEFAULT_CODEC_BACKEND;
594 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595
596 /*
597 * This function is to make sure that all the usecases that are active on
598 * the hardware codec backend are always routed to any one device that is
599 * handled by the hardware codec.
600 * For example, if low-latency and deep-buffer usecases are currently active
601 * on speaker and out_set_parameters(headset) is received on low-latency
602 * output, then we have to make sure deep-buffer is also switched to headset,
603 * because of the limitation that both the devices cannot be enabled
604 * at the same time as they share the same backend.
605 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700606 /*
607 * This call is to check if we need to force routing for a particular stream
608 * If there is a backend configuration change for the device when a
609 * new stream starts, then ADM needs to be closed and re-opened with the new
610 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530611 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700612 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530613 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
614 snd_device);
615 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800617 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800618 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 for (i = 0; i < AUDIO_USECASE_MAX; i++)
620 switch_device[i] = false;
621
622 list_for_each(node, &adev->usecase_list) {
623 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530624
625 if (usecase == uc_info)
626 continue;
627 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
628 ALOGV("%s: backend_idx: %d,"
629 "usecase_backend_idx: %d, curr device: %s, usecase device:"
630 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530631 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800633 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700634 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
636 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530637 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530638 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700639 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700640 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641 switch_device[usecase->id] = true;
642 num_uc_to_switch++;
643 }
644 }
645
646 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700647 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530649 /* Make sure the previous devices to be disabled first and then enable the
650 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
653 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700654 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 }
656 }
657
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700662 }
663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 /* Re-route all the usecases on the shared backend other than the
666 specified usecase to new snd devices */
667 list_for_each(node, &adev->usecase_list) {
668 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530669 /* Update the out_snd_device only for the usecases that are enabled here */
670 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
671 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530672 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 }
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 }
676}
677
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700678static void check_and_route_capture_usecases(struct audio_device *adev,
679 struct audio_usecase *uc_info,
680 snd_device_t snd_device)
681{
682 struct listnode *node;
683 struct audio_usecase *usecase;
684 bool switch_device[AUDIO_USECASE_MAX];
685 int i, num_uc_to_switch = 0;
686
687 /*
688 * This function is to make sure that all the active capture usecases
689 * are always routed to the same input sound device.
690 * For example, if audio-record and voice-call usecases are currently
691 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
692 * is received for voice call then we have to make sure that audio-record
693 * usecase is also switched to earpiece i.e. voice-dmic-ef,
694 * because of the limitation that two devices cannot be enabled
695 * at the same time if they share the same backend.
696 */
697 for (i = 0; i < AUDIO_USECASE_MAX; i++)
698 switch_device[i] = false;
699
700 list_for_each(node, &adev->usecase_list) {
701 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800702 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700704 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700705 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
706 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700707 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700708 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
709 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700710 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 switch_device[usecase->id] = true;
713 num_uc_to_switch++;
714 }
715 }
716
717 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530720 /* Make sure the previous devices to be disabled first and then enable the
721 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700722 list_for_each(node, &adev->usecase_list) {
723 usecase = node_to_item(node, struct audio_usecase, list);
724 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800726 }
727 }
728
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 }
734 }
735
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 /* Re-route all the usecases on the shared backend other than the
737 specified usecase to new snd devices */
738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
740 /* Update the in_snd_device only before enabling the audio route */
741 if (switch_device[usecase->id] ) {
742 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800743 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530744 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 }
746 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700747 }
748}
749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700751static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700753 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700754 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800755
756 switch (channels) {
757 /*
758 * Do not handle stereo output in Multi-channel cases
759 * Stereo case is handled in normal playback path
760 */
761 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 break;
769 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700770 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777 break;
778 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700779 ALOGE("HDMI does not support multi channel playback");
780 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781 break;
782 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784}
785
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800786audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
787 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700788{
789 struct audio_usecase *usecase;
790 struct listnode *node;
791
792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800794 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795 ALOGV("%s: usecase id %d", __func__, usecase->id);
796 return usecase->id;
797 }
798 }
799 return USECASE_INVALID;
800}
801
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700802struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804{
805 struct audio_usecase *usecase;
806 struct listnode *node;
807
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 if (usecase->id == uc_id)
811 return usecase;
812 }
813 return NULL;
814}
815
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700816int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 snd_device_t out_snd_device = SND_DEVICE_NONE;
819 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 struct audio_usecase *usecase = NULL;
821 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800822 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800823 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800824 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800825 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 usecase = get_usecase_from_list(adev, uc_id);
829 if (usecase == NULL) {
830 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
831 return -EINVAL;
832 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800834 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800835 (usecase->type == VOIP_CALL) ||
836 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700837 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800838 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700839 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 usecase->devices = usecase->stream.out->devices;
841 } else {
842 /*
843 * If the voice call is active, use the sound devices of voice call usecase
844 * so that it would not result any device switch. All the usecases will
845 * be switched to new device when select_devices() is called for voice call
846 * usecase. This is to avoid switching devices for voice call when
847 * check_usecases_codec_backend() is called below.
848 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700849 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700850 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800851 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700852 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
853 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700854 in_snd_device = vc_usecase->in_snd_device;
855 out_snd_device = vc_usecase->out_snd_device;
856 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800857 } else if (voice_extn_compress_voip_is_active(adev)) {
858 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530860 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700861 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800862 in_snd_device = voip_usecase->in_snd_device;
863 out_snd_device = voip_usecase->out_snd_device;
864 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800865 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800866 hfp_ucid = audio_extn_hfp_get_usecase();
867 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800869 in_snd_device = hfp_usecase->in_snd_device;
870 out_snd_device = hfp_usecase->out_snd_device;
871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 }
873 if (usecase->type == PCM_PLAYBACK) {
874 usecase->devices = usecase->stream.out->devices;
875 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700876 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700877 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800878 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700879 if (usecase->stream.out == adev->primary_output &&
880 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800881 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700882 select_devices(adev, adev->active_input->usecase);
883 }
884 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 } else if (usecase->type == PCM_CAPTURE) {
886 usecase->devices = usecase->stream.in->device;
887 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700888 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530890 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
891 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
892 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
893 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700894 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800895 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
897 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700898 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700899 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902 }
903
904 if (out_snd_device == usecase->out_snd_device &&
905 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906 return 0;
907 }
908
sangwoobc677242013-08-08 16:53:43 +0900909 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700910 out_snd_device, platform_get_snd_device_name(out_snd_device),
911 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 /*
914 * Limitation: While in call, to do a device switch we need to disable
915 * and enable both RX and TX devices though one of them is same as current
916 * device.
917 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700918 if ((usecase->type == VOICE_CALL) &&
919 (usecase->in_snd_device != SND_DEVICE_NONE) &&
920 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700921 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700922 }
923
924 if (((usecase->type == VOICE_CALL) ||
925 (usecase->type == VOIP_CALL)) &&
926 (usecase->out_snd_device != SND_DEVICE_NONE)) {
927 /* Disable sidetone only if voice/voip call already exists */
928 if (voice_is_call_state_active(adev) ||
929 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700930 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800931 }
932
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 /* Disable current sound devices */
934 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700935 disable_audio_route(adev, usecase);
936 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 }
938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700940 disable_audio_route(adev, usecase);
941 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800942 }
943
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800944 /* Applicable only on the targets that has external modem.
945 * New device information should be sent to modem before enabling
946 * the devices to reduce in-call device switch time.
947 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700948 if ((usecase->type == VOICE_CALL) &&
949 (usecase->in_snd_device != SND_DEVICE_NONE) &&
950 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800951 status = platform_switch_voice_call_enable_device_config(adev->platform,
952 out_snd_device,
953 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700954 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800955
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 /* Enable new sound devices */
957 if (out_snd_device != SND_DEVICE_NONE) {
958 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
959 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700960 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 }
962
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 if (in_snd_device != SND_DEVICE_NONE) {
964 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700965 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967
Avinash Vaish71a8b972014-07-24 15:36:33 +0530968 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700969 status = platform_switch_voice_call_device_post(adev->platform,
970 out_snd_device,
971 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530972 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700973 /* Enable sidetone only if voice/voip call already exists */
974 if (voice_is_call_state_active(adev) ||
975 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700976 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530977 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800978
sangwoo170731f2013-06-08 15:36:36 +0900979 usecase->in_snd_device = in_snd_device;
980 usecase->out_snd_device = out_snd_device;
981
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530982 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700983 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530984 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700985 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530986 usecase->stream.out->flags,
987 usecase->stream.out->format,
988 usecase->stream.out->sample_rate,
989 usecase->stream.out->bit_width,
990 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700991 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530992 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700993
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700994 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900995
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800996 /* Applicable only on the targets that has external modem.
997 * Enable device command should be sent to modem only after
998 * enabling voice call mixer controls
999 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001000 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001001 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1002 out_snd_device,
1003 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301004 ALOGD("%s: done",__func__);
1005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006 return status;
1007}
1008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001009static int stop_input_stream(struct stream_in *in)
1010{
1011 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 struct audio_usecase *uc_info;
1013 struct audio_device *adev = in->dev;
1014
Eric Laurentc8400632013-02-14 19:04:54 -08001015 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016
Eric Laurent994a6932013-07-17 11:51:42 -07001017 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001018 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019 uc_info = get_usecase_from_list(adev, in->usecase);
1020 if (uc_info == NULL) {
1021 ALOGE("%s: Could not find the usecase (%d) in the list",
1022 __func__, in->usecase);
1023 return -EINVAL;
1024 }
1025
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001026 /* Close in-call recording streams */
1027 voice_check_and_stop_incall_rec_usecase(adev, in);
1028
Eric Laurent150dbfe2013-02-27 14:31:02 -08001029 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001030 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031
1032 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001033 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001035 list_remove(&uc_info->list);
1036 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037
Eric Laurent994a6932013-07-17 11:51:42 -07001038 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 return ret;
1040}
1041
1042int start_input_stream(struct stream_in *in)
1043{
1044 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001045 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 struct audio_usecase *uc_info;
1047 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301048 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301050 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1051 if (get_usecase_from_list(adev, usecase) == NULL)
1052 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301053 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1054 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001055
Naresh Tanniru80659832014-06-04 18:17:56 +05301056
1057 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301058 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301059 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301060 goto error_config;
1061 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301062
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001063 /* Check if source matches incall recording usecase criteria */
1064 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1065 if (ret)
1066 goto error_config;
1067 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301068 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1069
1070 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1071 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1072 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1073 goto error_config;
1074 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001075
Eric Laurentb23d5282013-05-14 15:27:20 -07001076 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 if (in->pcm_device_id < 0) {
1078 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1079 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001080 ret = -EINVAL;
1081 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083
1084 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001086
1087 if (!uc_info) {
1088 ret = -ENOMEM;
1089 goto error_config;
1090 }
1091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092 uc_info->id = in->usecase;
1093 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001094 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 uc_info->devices = in->device;
1096 uc_info->in_snd_device = SND_DEVICE_NONE;
1097 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001099 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301100 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102
Eric Laurentc8400632013-02-14 19:04:54 -08001103 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001104 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1105
1106 unsigned int flags = PCM_IN;
1107 unsigned int pcm_open_retry_count = 0;
1108
1109 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1110 flags |= PCM_MMAP | PCM_NOIRQ;
1111 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1112 }
1113
1114 while (1) {
1115 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1116 flags, &in->config);
1117 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1118 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1119 if (in->pcm != NULL) {
1120 pcm_close(in->pcm);
1121 in->pcm = NULL;
1122 }
1123 if (pcm_open_retry_count-- == 0) {
1124 ret = -EIO;
1125 goto error_open;
1126 }
1127 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1128 continue;
1129 }
1130 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301132 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301133
Eric Laurent994a6932013-07-17 11:51:42 -07001134 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001135 return ret;
1136
1137error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301139 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001140
1141error_config:
1142 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001143 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001144
1145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146}
1147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001148/* must be called with out->lock locked */
1149static int send_offload_cmd_l(struct stream_out* out, int command)
1150{
1151 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1152
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001153 if (!cmd) {
1154 ALOGE("failed to allocate mem for command 0x%x", command);
1155 return -ENOMEM;
1156 }
1157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001158 ALOGVV("%s %d", __func__, command);
1159
1160 cmd->cmd = command;
1161 list_add_tail(&out->offload_cmd_list, &cmd->node);
1162 pthread_cond_signal(&out->offload_cond);
1163 return 0;
1164}
1165
1166/* must be called iwth out->lock locked */
1167static void stop_compressed_output_l(struct stream_out *out)
1168{
1169 out->offload_state = OFFLOAD_STATE_IDLE;
1170 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001171 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001172 if (out->compr != NULL) {
1173 compress_stop(out->compr);
1174 while (out->offload_thread_blocked) {
1175 pthread_cond_wait(&out->cond, &out->lock);
1176 }
1177 }
1178}
1179
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001180bool is_offload_usecase(audio_usecase_t uc_id)
1181{
1182 unsigned int i;
1183 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1184 if (uc_id == offload_usecases[i])
1185 return true;
1186 }
1187 return false;
1188}
1189
1190static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1191{
1192 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1193 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1194 char value[PROPERTY_VALUE_MAX] = {0};
1195
1196 property_get("audio.offload.multiple.enabled", value, NULL);
1197 if (!(atoi(value) || !strncmp("true", value, 4)))
1198 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1199
1200 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1201 for (i = 0; i < num_usecase; i++) {
1202 if (!(adev->offload_usecases_state & (0x1<<i))) {
1203 adev->offload_usecases_state |= 0x1 << i;
1204 ret = offload_usecases[i];
1205 break;
1206 }
1207 }
1208 ALOGV("%s: offload usecase is %d", __func__, ret);
1209 return ret;
1210}
1211
1212static void free_offload_usecase(struct audio_device *adev,
1213 audio_usecase_t uc_id)
1214{
1215 unsigned int i;
1216 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1217 if (offload_usecases[i] == uc_id) {
1218 adev->offload_usecases_state &= ~(0x1<<i);
1219 break;
1220 }
1221 }
1222 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1223}
1224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001225static void *offload_thread_loop(void *context)
1226{
1227 struct stream_out *out = (struct stream_out *) context;
1228 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001229 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001231 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1232 set_sched_policy(0, SP_FOREGROUND);
1233 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1234
1235 ALOGV("%s", __func__);
1236 pthread_mutex_lock(&out->lock);
1237 for (;;) {
1238 struct offload_cmd *cmd = NULL;
1239 stream_callback_event_t event;
1240 bool send_callback = false;
1241
1242 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1243 __func__, list_empty(&out->offload_cmd_list),
1244 out->offload_state);
1245 if (list_empty(&out->offload_cmd_list)) {
1246 ALOGV("%s SLEEPING", __func__);
1247 pthread_cond_wait(&out->offload_cond, &out->lock);
1248 ALOGV("%s RUNNING", __func__);
1249 continue;
1250 }
1251
1252 item = list_head(&out->offload_cmd_list);
1253 cmd = node_to_item(item, struct offload_cmd, node);
1254 list_remove(item);
1255
1256 ALOGVV("%s STATE %d CMD %d out->compr %p",
1257 __func__, out->offload_state, cmd->cmd, out->compr);
1258
1259 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1260 free(cmd);
1261 break;
1262 }
1263
1264 if (out->compr == NULL) {
1265 ALOGE("%s: Compress handle is NULL", __func__);
1266 pthread_cond_signal(&out->cond);
1267 continue;
1268 }
1269 out->offload_thread_blocked = true;
1270 pthread_mutex_unlock(&out->lock);
1271 send_callback = false;
1272 switch(cmd->cmd) {
1273 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001274 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001276 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 send_callback = true;
1278 event = STREAM_CBK_EVENT_WRITE_READY;
1279 break;
1280 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001281 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301282 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001283 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301284 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301286 if (ret < 0)
1287 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301288 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301289 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001290 compress_drain(out->compr);
1291 else
1292 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301293 if (ret != -ENETRESET) {
1294 send_callback = true;
1295 event = STREAM_CBK_EVENT_DRAIN_READY;
1296 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1297 } else
1298 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001299 break;
1300 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001301 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001302 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001303 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 send_callback = true;
1305 event = STREAM_CBK_EVENT_DRAIN_READY;
1306 break;
1307 default:
1308 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1309 break;
1310 }
1311 pthread_mutex_lock(&out->lock);
1312 out->offload_thread_blocked = false;
1313 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001314 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001315 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001316 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001317 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 free(cmd);
1319 }
1320
1321 pthread_cond_signal(&out->cond);
1322 while (!list_empty(&out->offload_cmd_list)) {
1323 item = list_head(&out->offload_cmd_list);
1324 list_remove(item);
1325 free(node_to_item(item, struct offload_cmd, node));
1326 }
1327 pthread_mutex_unlock(&out->lock);
1328
1329 return NULL;
1330}
1331
1332static int create_offload_callback_thread(struct stream_out *out)
1333{
1334 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1335 list_init(&out->offload_cmd_list);
1336 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1337 offload_thread_loop, out);
1338 return 0;
1339}
1340
1341static int destroy_offload_callback_thread(struct stream_out *out)
1342{
1343 pthread_mutex_lock(&out->lock);
1344 stop_compressed_output_l(out);
1345 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1346
1347 pthread_mutex_unlock(&out->lock);
1348 pthread_join(out->offload_thread, (void **) NULL);
1349 pthread_cond_destroy(&out->offload_cond);
1350
1351 return 0;
1352}
1353
Eric Laurent07eeafd2013-10-06 12:52:49 -07001354static bool allow_hdmi_channel_config(struct audio_device *adev)
1355{
1356 struct listnode *node;
1357 struct audio_usecase *usecase;
1358 bool ret = true;
1359
1360 list_for_each(node, &adev->usecase_list) {
1361 usecase = node_to_item(node, struct audio_usecase, list);
1362 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1363 /*
1364 * If voice call is already existing, do not proceed further to avoid
1365 * disabling/enabling both RX and TX devices, CSD calls, etc.
1366 * Once the voice call done, the HDMI channels can be configured to
1367 * max channels of remaining use cases.
1368 */
1369 if (usecase->id == USECASE_VOICE_CALL) {
1370 ALOGD("%s: voice call is active, no change in HDMI channels",
1371 __func__);
1372 ret = false;
1373 break;
1374 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1375 ALOGD("%s: multi channel playback is active, "
1376 "no change in HDMI channels", __func__);
1377 ret = false;
1378 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001379 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001380 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001381 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1382 ", no change in HDMI channels", __func__,
1383 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001384 ret = false;
1385 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001386 }
1387 }
1388 }
1389 return ret;
1390}
1391
1392static int check_and_set_hdmi_channels(struct audio_device *adev,
1393 unsigned int channels)
1394{
1395 struct listnode *node;
1396 struct audio_usecase *usecase;
1397
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001398 unsigned int supported_channels = platform_edid_get_max_channels(
1399 adev->platform);
1400 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 /* Check if change in HDMI channel config is allowed */
1402 if (!allow_hdmi_channel_config(adev))
1403 return 0;
1404
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001405 if (channels > supported_channels)
1406 channels = supported_channels;
1407
Eric Laurent07eeafd2013-10-06 12:52:49 -07001408 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001409 ALOGD("%s: Requested channels are same as current channels(%d)",
1410 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001411 return 0;
1412 }
1413
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001414 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001415 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001416 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 adev->cur_hdmi_channels = channels;
1418
1419 /*
1420 * Deroute all the playback streams routed to HDMI so that
1421 * the back end is deactivated. Note that backend will not
1422 * be deactivated if any one stream is connected to it.
1423 */
1424 list_for_each(node, &adev->usecase_list) {
1425 usecase = node_to_item(node, struct audio_usecase, list);
1426 if (usecase->type == PCM_PLAYBACK &&
1427 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001428 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 }
1430 }
1431
1432 /*
1433 * Enable all the streams disabled above. Now the HDMI backend
1434 * will be activated with new channel configuration
1435 */
1436 list_for_each(node, &adev->usecase_list) {
1437 usecase = node_to_item(node, struct audio_usecase, list);
1438 if (usecase->type == PCM_PLAYBACK &&
1439 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001440 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001441 }
1442 }
1443
1444 return 0;
1445}
1446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447static int stop_output_stream(struct stream_out *out)
1448{
1449 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 struct audio_usecase *uc_info;
1451 struct audio_device *adev = out->dev;
1452
Eric Laurent994a6932013-07-17 11:51:42 -07001453 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 uc_info = get_usecase_from_list(adev, out->usecase);
1456 if (uc_info == NULL) {
1457 ALOGE("%s: Could not find the usecase (%d) in the list",
1458 __func__, out->usecase);
1459 return -EINVAL;
1460 }
1461
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001462 if (is_offload_usecase(out->usecase) &&
1463 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001464 if (adev->visualizer_stop_output != NULL)
1465 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001466
1467 audio_extn_dts_remove_state_notifier_node(out->usecase);
1468
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001469 if (adev->offload_effects_stop_output != NULL)
1470 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1471 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001472
Eric Laurent150dbfe2013-02-27 14:31:02 -08001473 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
1476 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001479 list_remove(&uc_info->list);
1480 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001482 if (is_offload_usecase(out->usecase) &&
1483 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1484 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1485 ALOGV("Disable passthrough , reset mixer to pcm");
1486 /* NO_PASSTHROUGH */
1487 out->compr_config.codec->compr_passthr = 0;
1488 audio_extn_dolby_set_hdmi_config(adev, out);
1489 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1490 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001491 /* Must be called after removing the usecase from list */
1492 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1493 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1494
Eric Laurent994a6932013-07-17 11:51:42 -07001495 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 return ret;
1497}
1498
1499int start_output_stream(struct stream_out *out)
1500{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001502 int sink_channels = 0;
1503 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 struct audio_usecase *uc_info;
1505 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301506 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001508 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1509 ret = -EINVAL;
1510 goto error_config;
1511 }
1512
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301513 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1514 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1515 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301516
Naresh Tanniru80659832014-06-04 18:17:56 +05301517 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301518 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301519 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301520 goto error_config;
1521 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301522
Eric Laurentb23d5282013-05-14 15:27:20 -07001523 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 if (out->pcm_device_id < 0) {
1525 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1526 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001527 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001528 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 }
1530
1531 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001532
1533 if (!uc_info) {
1534 ret = -ENOMEM;
1535 goto error_config;
1536 }
1537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 uc_info->id = out->usecase;
1539 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001540 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001541 uc_info->devices = out->devices;
1542 uc_info->in_snd_device = SND_DEVICE_NONE;
1543 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001544 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001545 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001546 if (is_offload_usecase(out->usecase)) {
1547 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001548 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1549 }
1550 }
Mingming Yin9c041392014-05-01 15:37:31 -07001551 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1552 if (!strncmp("true", prop_value, 4)) {
1553 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001554 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1555 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001556 check_and_set_hdmi_channels(adev, sink_channels);
1557 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 if (is_offload_usecase(out->usecase)) {
1559 unsigned int ch_count = out->compr_config.codec->ch_in;
1560 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1561 /* backend channel config for passthrough stream is stereo */
1562 ch_count = 2;
1563 check_and_set_hdmi_channels(adev, ch_count);
1564 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001565 check_and_set_hdmi_channels(adev, out->config.channels);
1566 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001567 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001568 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001569 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 select_devices(adev, out->usecase);
1572
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001573 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1574 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001575 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001576 unsigned int flags = PCM_OUT;
1577 unsigned int pcm_open_retry_count = 0;
1578 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1579 flags |= PCM_MMAP | PCM_NOIRQ;
1580 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1581 } else
1582 flags |= PCM_MONOTONIC;
1583
1584 while (1) {
1585 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1586 flags, &out->config);
1587 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1588 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1589 if (out->pcm != NULL) {
1590 pcm_close(out->pcm);
1591 out->pcm = NULL;
1592 }
1593 if (pcm_open_retry_count-- == 0) {
1594 ret = -EIO;
1595 goto error_open;
1596 }
1597 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1598 continue;
1599 }
1600 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001601 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001602 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1603 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001604 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001605 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1606 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001608 out->compr = compress_open(adev->snd_card,
1609 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001610 COMPRESS_IN, &out->compr_config);
1611 if (out->compr && !is_compress_ready(out->compr)) {
1612 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1613 compress_close(out->compr);
1614 out->compr = NULL;
1615 ret = -EIO;
1616 goto error_open;
1617 }
1618 if (out->offload_callback)
1619 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001620
Fred Oh3f43e742015-03-04 18:42:34 -08001621 /* Since small bufs uses blocking writes, a write will be blocked
1622 for the default max poll time (20s) in the event of an SSR.
1623 Reduce the poll time to observe and deal with SSR faster.
1624 */
1625 if (out->use_small_bufs) {
1626 compress_set_max_poll_wait(out->compr, 1000);
1627 }
1628
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001629 audio_extn_dts_create_state_notifier_node(out->usecase);
1630 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1631 popcount(out->channel_mask),
1632 out->playback_started);
1633
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001634#ifdef DS1_DOLBY_DDP_ENABLED
1635 if (audio_extn_is_dolby_format(out->format))
1636 audio_extn_dolby_send_ddp_endp_params(adev);
1637#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001638 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1639 if (adev->visualizer_start_output != NULL)
1640 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1641 if (adev->offload_effects_start_output != NULL)
1642 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001643 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
Eric Laurent994a6932013-07-17 11:51:42 -07001646 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001650error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001651 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652}
1653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654static int check_input_parameters(uint32_t sample_rate,
1655 audio_format_t format,
1656 int channel_count)
1657{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001658 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001660 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001661 !voice_extn_compress_voip_is_format_supported(format) &&
1662 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001663
1664 switch (channel_count) {
1665 case 1:
1666 case 2:
1667 case 6:
1668 break;
1669 default:
1670 ret = -EINVAL;
1671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
1673 switch (sample_rate) {
1674 case 8000:
1675 case 11025:
1676 case 12000:
1677 case 16000:
1678 case 22050:
1679 case 24000:
1680 case 32000:
1681 case 44100:
1682 case 48000:
1683 break;
1684 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001685 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686 }
1687
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001688 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689}
1690
1691static size_t get_input_buffer_size(uint32_t sample_rate,
1692 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001693 int channel_count,
1694 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695{
1696 size_t size = 0;
1697
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001698 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1699 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001701 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001702 if (is_low_latency)
1703 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001704 /* ToDo: should use frame_size computed based on the format and
1705 channel_count here. */
1706 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001708 /* make sure the size is multiple of 32 bytes
1709 * At 48 kHz mono 16-bit PCM:
1710 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1711 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1712 */
1713 size += 0x1f;
1714 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001715
1716 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717}
1718
1719static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1720{
1721 struct stream_out *out = (struct stream_out *)stream;
1722
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724}
1725
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001726static int out_set_sample_rate(struct audio_stream *stream __unused,
1727 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728{
1729 return -ENOSYS;
1730}
1731
1732static size_t out_get_buffer_size(const struct audio_stream *stream)
1733{
1734 struct stream_out *out = (struct stream_out *)stream;
1735
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001736 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001738 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1739 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001741 return out->config.period_size *
1742 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743}
1744
1745static uint32_t out_get_channels(const struct audio_stream *stream)
1746{
1747 struct stream_out *out = (struct stream_out *)stream;
1748
1749 return out->channel_mask;
1750}
1751
1752static audio_format_t out_get_format(const struct audio_stream *stream)
1753{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 struct stream_out *out = (struct stream_out *)stream;
1755
1756 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757}
1758
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001759static int out_set_format(struct audio_stream *stream __unused,
1760 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761{
1762 return -ENOSYS;
1763}
1764
1765static int out_standby(struct audio_stream *stream)
1766{
1767 struct stream_out *out = (struct stream_out *)stream;
1768 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301770 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1771 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001772 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1773 /* Ignore standby in case of voip call because the voip output
1774 * stream is closed in adev_close_output_stream()
1775 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301776 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001777 return 0;
1778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001782 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001784 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 if (out->pcm) {
1786 pcm_close(out->pcm);
1787 out->pcm = NULL;
1788 }
1789 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001790 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001792 out->gapless_mdata.encoder_delay = 0;
1793 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 if (out->compr != NULL) {
1795 compress_close(out->compr);
1796 out->compr = NULL;
1797 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001798 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001800 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 }
1802 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001803 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 return 0;
1805}
1806
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001807static int out_dump(const struct audio_stream *stream __unused,
1808 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809{
1810 return 0;
1811}
1812
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001813static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1814{
1815 int ret = 0;
1816 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301817 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001818
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 return -EINVAL;
1822 }
1823
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001824 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1825 if (ret >= 0) {
1826 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1827 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1828 ALOGV("ADTS format is set in offload mode");
1829 }
Yadav Anamikafbcef792015-08-19 16:15:00 +05301830 out->send_new_metadata = 1;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001831 }
1832
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301833 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001834
Yadav Anamikafbcef792015-08-19 16:15:00 +05301835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1836 if(ret >= 0)
1837 is_meta_data_params = true;
1838 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1839 if(ret >= 0)
1840 is_meta_data_params = true;
1841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1842 if(ret >= 0)
1843 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1845 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301846 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301847 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1850 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301851 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301852 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853 }
1854
Yadav Anamikafbcef792015-08-19 16:15:00 +05301855 if(!is_meta_data_params) {
1856 ALOGV("%s: Not gapless meta data params", __func__);
1857 return 0;
1858 }
1859 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 ALOGV("%s new encoder delay %u and padding %u", __func__,
1861 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1862
1863 return 0;
1864}
1865
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001866static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1867{
1868 return out == adev->primary_output || out == adev->voice_tx_output;
1869}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1872{
1873 struct stream_out *out = (struct stream_out *)stream;
1874 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 struct audio_usecase *usecase;
1876 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 struct str_parms *parms;
1878 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001879 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001880 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881
sangwoobc677242013-08-08 16:53:43 +09001882 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301885 if (!parms)
1886 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001887 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1888 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001891 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001893 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301894 * When HDMI cable is unplugged/usb hs is disconnected the
1895 * music playback is paused and the policy manager sends routing=0
1896 * But the audioflingercontinues to write data until standby time
1897 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 * Avoid this by routing audio to speaker until standby.
1899 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301900 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1901 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001903 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1904 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 }
1906
1907 /*
1908 * select_devices() call below switches all the usecases on the same
1909 * backend to the new device. Refer to check_usecases_codec_backend() in
1910 * the select_devices(). But how do we undo this?
1911 *
1912 * For example, music playback is active on headset (deep-buffer usecase)
1913 * and if we go to ringtones and select a ringtone, low-latency usecase
1914 * will be started on headset+speaker. As we can't enable headset+speaker
1915 * and headset devices at the same time, select_devices() switches the music
1916 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1917 * So when the ringtone playback is completed, how do we undo the same?
1918 *
1919 * We are relying on the out_set_parameters() call on deep-buffer output,
1920 * once the ringtone playback is ended.
1921 * NOTE: We should not check if the current devices are same as new devices.
1922 * Because select_devices() must be called to switch back the music
1923 * playback to headset.
1924 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001925 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 out->devices = val;
1927
1928 if (!out->standby)
1929 select_devices(adev, out->usecase);
1930
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001931 if (output_drives_call(adev, out)) {
1932 if(!voice_is_in_call(adev)) {
1933 if (adev->mode == AUDIO_MODE_IN_CALL) {
1934 adev->current_call_output = out;
1935 ret = voice_start_call(adev);
1936 }
1937 } else {
1938 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001939 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001940 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001941 }
1942 }
1943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001945 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001947
1948 if (out == adev->primary_output) {
1949 pthread_mutex_lock(&adev->lock);
1950 audio_extn_set_parameters(adev, parms);
1951 pthread_mutex_unlock(&adev->lock);
1952 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001953 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001954 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001955 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001956
1957 audio_extn_dts_create_state_notifier_node(out->usecase);
1958 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1959 popcount(out->channel_mask),
1960 out->playback_started);
1961
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001962 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001963 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301966error:
Eric Laurent994a6932013-07-17 11:51:42 -07001967 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 return ret;
1969}
1970
1971static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1972{
1973 struct stream_out *out = (struct stream_out *)stream;
1974 struct str_parms *query = str_parms_create_str(keys);
1975 char *str;
1976 char value[256];
1977 struct str_parms *reply = str_parms_create();
1978 size_t i, j;
1979 int ret;
1980 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001981
1982 if (!query || !reply) {
1983 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1984 return NULL;
1985 }
1986
Eric Laurent994a6932013-07-17 11:51:42 -07001987 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1989 if (ret >= 0) {
1990 value[0] = '\0';
1991 i = 0;
1992 while (out->supported_channel_masks[i] != 0) {
1993 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1994 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1995 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001996 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001998 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 first = false;
2000 break;
2001 }
2002 }
2003 i++;
2004 }
2005 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2006 str = str_parms_to_str(reply);
2007 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002008 voice_extn_out_get_parameters(out, query, reply);
2009 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002010 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002011 free(str);
2012 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002013 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002015
2016 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2017 if (ret >= 0) {
2018 value[0] = '\0';
2019 i = 0;
2020 first = true;
2021 while (out->supported_formats[i] != 0) {
2022 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2023 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2024 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002025 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002026 }
2027 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2028 first = false;
2029 break;
2030 }
2031 }
2032 i++;
2033 }
2034 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2035 str = str_parms_to_str(reply);
2036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 str_parms_destroy(query);
2038 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002039 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 return str;
2041}
2042
2043static uint32_t out_get_latency(const struct audio_stream_out *stream)
2044{
2045 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002046 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Alexy Josephaa54c872014-12-03 02:46:47 -08002048 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002049 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002050 } else {
2051 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002053 }
2054
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302055 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002056 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057}
2058
2059static int out_set_volume(struct audio_stream_out *stream, float left,
2060 float right)
2061{
Eric Laurenta9024de2013-04-04 09:19:12 -07002062 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 int volume[2];
2064
Eric Laurenta9024de2013-04-04 09:19:12 -07002065 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2066 /* only take left channel into account: the API is for stereo anyway */
2067 out->muted = (left == 0.0f);
2068 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002069 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002070 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2071 /*
2072 * Set mute or umute on HDMI passthrough stream.
2073 * Only take left channel into account.
2074 * Mute is 0 and unmute 1
2075 */
2076 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2077 } else {
2078 char mixer_ctl_name[128];
2079 struct audio_device *adev = out->dev;
2080 struct mixer_ctl *ctl;
2081 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002082 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002084 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2085 "Compress Playback %d Volume", pcm_device_id);
2086 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2087 if (!ctl) {
2088 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2089 __func__, mixer_ctl_name);
2090 return -EINVAL;
2091 }
2092 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2093 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2094 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2095 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002097 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 return -ENOSYS;
2100}
2101
2102static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2103 size_t bytes)
2104{
2105 struct stream_out *out = (struct stream_out *)stream;
2106 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302107 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002108 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302111
Naresh Tanniru80659832014-06-04 18:17:56 +05302112 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002113 // increase written size during SSR to avoid mismatch
2114 // with the written frames count in AF
2115 if (!is_offload_usecase(out->usecase))
2116 out->written += bytes / (out->config.channels * sizeof(short));
2117
Naresh Tanniru80659832014-06-04 18:17:56 +05302118 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302119 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302120 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302121 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002122 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302123 //during SSR for compress usecase we should return error to flinger
2124 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2125 pthread_mutex_unlock(&out->lock);
2126 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 }
2128 }
2129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002131 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002132 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002133 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2134 ret = voice_extn_compress_voip_start_output_stream(out);
2135 else
2136 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002137 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002140 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 goto exit;
2142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302145 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2146 setChannelStatus(out, buffer, bytes);
2147 adev->mChannelStatusSet = true;
2148 }
2149
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002150 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002151 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002153 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002154 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2155 out->send_new_metadata = 0;
2156 }
2157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302159 if (ret < 0)
2160 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002161 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002162 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302163 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 } else if (-ENETRESET == ret) {
2166 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2167 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2168 pthread_mutex_unlock(&out->lock);
2169 out_standby(&out->stream.common);
2170 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302172 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002174 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 out->playback_started = 1;
2176 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002177
2178 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2179 popcount(out->channel_mask),
2180 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
2182 pthread_mutex_unlock(&out->lock);
2183 return ret;
2184 } else {
2185 if (out->pcm) {
2186 if (out->muted)
2187 memset((void *)buffer, 0, bytes);
2188 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002189 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2190 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2191 else
2192 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302193 if (ret < 0)
2194 ret = -errno;
2195 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002196 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 }
2199
2200exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302201 /* ToDo: There may be a corner case when SSR happens back to back during
2202 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302203 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205 }
2206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 pthread_mutex_unlock(&out->lock);
2208
2209 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002210 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002211 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302212 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302213 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302214 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302215 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302216 out->standby = true;
2217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002219 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 out_get_sample_rate(&out->stream.common));
2221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 }
2223 return bytes;
2224}
2225
2226static int out_get_render_position(const struct audio_stream_out *stream,
2227 uint32_t *dsp_frames)
2228{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302230 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002231
2232 if (dsp_frames == NULL)
2233 return -EINVAL;
2234
2235 *dsp_frames = 0;
2236 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002237 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 pthread_mutex_lock(&out->lock);
2239 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302240 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302242 if (ret < 0)
2243 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 ALOGVV("%s rendered frames %d sample_rate %d",
2245 __func__, *dsp_frames, out->sample_rate);
2246 }
2247 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302248 if (-ENETRESET == ret) {
2249 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2250 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2251 return -EINVAL;
2252 } else if(ret < 0) {
2253 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2254 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302255 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2256 /*
2257 * Handle corner case where compress session is closed during SSR
2258 * and timestamp is queried
2259 */
2260 ALOGE(" ERROR: sound card not active, return error");
2261 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302262 } else {
2263 return 0;
2264 }
Zhou Song32a556e2015-05-05 10:46:56 +08002265 } else if (audio_is_linear_pcm(out->format)) {
2266 *dsp_frames = out->written;
2267 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 } else
2269 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270}
2271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002272static int out_add_audio_effect(const struct audio_stream *stream __unused,
2273 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274{
2275 return 0;
2276}
2277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002278static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2279 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280{
2281 return 0;
2282}
2283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002284static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2285 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286{
2287 return -EINVAL;
2288}
2289
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002290static int out_get_presentation_position(const struct audio_stream_out *stream,
2291 uint64_t *frames, struct timespec *timestamp)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002296
2297 pthread_mutex_lock(&out->lock);
2298
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002299 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002300 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302301 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002302 &out->sample_rate);
2303 ALOGVV("%s rendered frames %ld sample_rate %d",
2304 __func__, dsp_frames, out->sample_rate);
2305 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302306 if (ret < 0)
2307 ret = -errno;
2308 if (-ENETRESET == ret) {
2309 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2310 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2311 ret = -EINVAL;
2312 } else
2313 ret = 0;
2314
Eric Laurent949a0892013-09-20 09:20:13 -07002315 /* this is the best we can do */
2316 clock_gettime(CLOCK_MONOTONIC, timestamp);
2317 }
2318 } else {
2319 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002321 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2322 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002323 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002324 // This adjustment accounts for buffering after app processor.
2325 // It is based on estimated DSP latency per use case, rather than exact.
2326 signed_frames -=
2327 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2328
Eric Laurent949a0892013-09-20 09:20:13 -07002329 // It would be unusual for this value to be negative, but check just in case ...
2330 if (signed_frames >= 0) {
2331 *frames = signed_frames;
2332 ret = 0;
2333 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002334 }
2335 }
2336 }
2337
2338 pthread_mutex_unlock(&out->lock);
2339
2340 return ret;
2341}
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343static int out_set_callback(struct audio_stream_out *stream,
2344 stream_callback_t callback, void *cookie)
2345{
2346 struct stream_out *out = (struct stream_out *)stream;
2347
2348 ALOGV("%s", __func__);
2349 pthread_mutex_lock(&out->lock);
2350 out->offload_callback = callback;
2351 out->offload_cookie = cookie;
2352 pthread_mutex_unlock(&out->lock);
2353 return 0;
2354}
2355
2356static int out_pause(struct audio_stream_out* stream)
2357{
2358 struct stream_out *out = (struct stream_out *)stream;
2359 int status = -ENOSYS;
2360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002362 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 pthread_mutex_lock(&out->lock);
2364 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302365 struct audio_device *adev = out->dev;
2366 int snd_scard_state = get_snd_card_state(adev);
2367
2368 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2369 status = compress_pause(out->compr);
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302373 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374 audio_extn_dts_notify_playback_state(out->usecase, 0,
2375 out->sample_rate, popcount(out->channel_mask),
2376 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 }
2378 pthread_mutex_unlock(&out->lock);
2379 }
2380 return status;
2381}
2382
2383static int out_resume(struct audio_stream_out* stream)
2384{
2385 struct stream_out *out = (struct stream_out *)stream;
2386 int status = -ENOSYS;
2387 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002388 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002389 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 status = 0;
2391 pthread_mutex_lock(&out->lock);
2392 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302393 struct audio_device *adev = out->dev;
2394 int snd_scard_state = get_snd_card_state(adev);
2395
2396 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2397 status = compress_resume(out->compr);
2398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002400
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302401 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2403 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 }
2405 pthread_mutex_unlock(&out->lock);
2406 }
2407 return status;
2408}
2409
2410static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2411{
2412 struct stream_out *out = (struct stream_out *)stream;
2413 int status = -ENOSYS;
2414 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002415 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 pthread_mutex_lock(&out->lock);
2417 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2418 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2419 else
2420 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2421 pthread_mutex_unlock(&out->lock);
2422 }
2423 return status;
2424}
2425
2426static int out_flush(struct audio_stream_out* stream)
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002431 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 pthread_mutex_lock(&out->lock);
2433 stop_compressed_output_l(out);
2434 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002435 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 return 0;
2437 }
2438 return -ENOSYS;
2439}
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441/** audio_stream_in implementation **/
2442static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->config.rate;
2447}
2448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002449static int in_set_sample_rate(struct audio_stream *stream __unused,
2450 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451{
2452 return -ENOSYS;
2453}
2454
2455static size_t in_get_buffer_size(const struct audio_stream *stream)
2456{
2457 struct stream_in *in = (struct stream_in *)stream;
2458
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2460 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002461 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2462 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002463
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002464 return in->config.period_size *
2465 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466}
2467
2468static uint32_t in_get_channels(const struct audio_stream *stream)
2469{
2470 struct stream_in *in = (struct stream_in *)stream;
2471
2472 return in->channel_mask;
2473}
2474
2475static audio_format_t in_get_format(const struct audio_stream *stream)
2476{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 struct stream_in *in = (struct stream_in *)stream;
2478
2479 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002482static int in_set_format(struct audio_stream *stream __unused,
2483 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484{
2485 return -ENOSYS;
2486}
2487
2488static int in_standby(struct audio_stream *stream)
2489{
2490 struct stream_in *in = (struct stream_in *)stream;
2491 struct audio_device *adev = in->dev;
2492 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302493 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2494 stream, in->usecase, use_case_table[in->usecase]);
2495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2497 /* Ignore standby in case of voip call because the voip input
2498 * stream is closed in adev_close_input_stream()
2499 */
2500 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2501 return status;
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002505 if (!in->standby && in->is_st_session) {
2506 ALOGD("%s: sound trigger pcm stop lab", __func__);
2507 audio_extn_sound_trigger_stop_lab(in);
2508 in->standby = 1;
2509 }
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002512 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002514 if (in->pcm) {
2515 pcm_close(in->pcm);
2516 in->pcm = NULL;
2517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
2521 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002522 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 return status;
2524}
2525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002526static int in_dump(const struct audio_stream *stream __unused,
2527 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528{
2529 return 0;
2530}
2531
2532static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535 struct audio_device *adev = in->dev;
2536 struct str_parms *parms;
2537 char *str;
2538 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002539 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302541 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 parms = str_parms_create_str(kvpairs);
2543
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302544 if (!parms)
2545 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002548
2549 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2550 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 val = atoi(value);
2552 /* no audio source uses val == 0 */
2553 if ((in->source != val) && (val != 0)) {
2554 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002555 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2556 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2557 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2558 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002559 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002560 err = voice_extn_compress_voip_open_input_stream(in);
2561 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002562 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002563 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002564 }
2565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
2567 }
2568
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002569 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2570 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002572 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 in->device = val;
2574 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002575 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002576 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578 }
2579
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002580done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002582 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
2584 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302585error:
Eric Laurent994a6932013-07-17 11:51:42 -07002586 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 return ret;
2588}
2589
2590static char* in_get_parameters(const struct audio_stream *stream,
2591 const char *keys)
2592{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 struct stream_in *in = (struct stream_in *)stream;
2594 struct str_parms *query = str_parms_create_str(keys);
2595 char *str;
2596 char value[256];
2597 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002598
2599 if (!query || !reply) {
2600 ALOGE("in_get_parameters: failed to create query or reply");
2601 return NULL;
2602 }
2603
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002604 ALOGV("%s: enter: keys - %s", __func__, keys);
2605
2606 voice_extn_in_get_parameters(in, query, reply);
2607
2608 str = str_parms_to_str(reply);
2609 str_parms_destroy(query);
2610 str_parms_destroy(reply);
2611
2612 ALOGV("%s: exit: returns - %s", __func__, str);
2613 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002616static int in_set_gain(struct audio_stream_in *stream __unused,
2617 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618{
2619 return 0;
2620}
2621
2622static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2623 size_t bytes)
2624{
2625 struct stream_in *in = (struct stream_in *)stream;
2626 struct audio_device *adev = in->dev;
2627 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302628 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302631
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002632 if (in->is_st_session) {
2633 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2634 /* Read from sound trigger HAL */
2635 audio_extn_sound_trigger_read(in, buffer, bytes);
2636 pthread_mutex_unlock(&in->lock);
2637 return bytes;
2638 }
2639
2640 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2641 ALOGD(" %s: sound card is not active/SSR state", __func__);
2642 ret= -EIO;;
2643 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302644 }
2645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002647 pthread_mutex_lock(&adev->lock);
2648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2649 ret = voice_extn_compress_voip_start_input_stream(in);
2650 else
2651 ret = start_input_stream(in);
2652 pthread_mutex_unlock(&adev->lock);
2653 if (ret != 0) {
2654 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
2656 in->standby = 0;
2657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
2659 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002660 if (audio_extn_ssr_get_enabled() &&
2661 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002662 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002663 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2664 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002665 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2666 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002667 else
2668 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302669 if (ret < 0)
2670 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672
2673 /*
2674 * Instead of writing zeroes here, we could trust the hardware
2675 * to always provide zeroes when muted.
2676 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302677 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2678 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 memset(buffer, 0, bytes);
2680
2681exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302682 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302683 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002684 if (-ENETRESET == ret)
2685 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 pthread_mutex_unlock(&in->lock);
2688
2689 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302690 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302691 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302692 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302693 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302694 in->standby = true;
2695 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302696 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002698 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002699 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302700 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 }
2702 return bytes;
2703}
2704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002705static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
2707 return 0;
2708}
2709
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710static int add_remove_audio_effect(const struct audio_stream *stream,
2711 effect_handle_t effect,
2712 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002714 struct stream_in *in = (struct stream_in *)stream;
2715 int status = 0;
2716 effect_descriptor_t desc;
2717
2718 status = (*effect)->get_descriptor(effect, &desc);
2719 if (status != 0)
2720 return status;
2721
2722 pthread_mutex_lock(&in->lock);
2723 pthread_mutex_lock(&in->dev->lock);
2724 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2725 in->enable_aec != enable &&
2726 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2727 in->enable_aec = enable;
2728 if (!in->standby)
2729 select_devices(in->dev, in->usecase);
2730 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002731 if (in->enable_ns != enable &&
2732 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2733 in->enable_ns = enable;
2734 if (!in->standby)
2735 select_devices(in->dev, in->usecase);
2736 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002737 pthread_mutex_unlock(&in->dev->lock);
2738 pthread_mutex_unlock(&in->lock);
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 return 0;
2741}
2742
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002743static int in_add_audio_effect(const struct audio_stream *stream,
2744 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
Eric Laurent994a6932013-07-17 11:51:42 -07002746 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002747 return add_remove_audio_effect(stream, effect, true);
2748}
2749
2750static int in_remove_audio_effect(const struct audio_stream *stream,
2751 effect_handle_t effect)
2752{
Eric Laurent994a6932013-07-17 11:51:42 -07002753 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002754 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755}
2756
2757static int adev_open_output_stream(struct audio_hw_device *dev,
2758 audio_io_handle_t handle,
2759 audio_devices_t devices,
2760 audio_output_flags_t flags,
2761 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002762 struct audio_stream_out **stream_out,
2763 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
2765 struct audio_device *adev = (struct audio_device *)dev;
2766 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002767 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002768 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302771
2772 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2773 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2774 ALOGE(" sound card is not active rejecting compress output open request");
2775 return -EINVAL;
2776 }
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2779
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302780 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2781 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2782 devices, flags, &out->stream);
2783
2784
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002785 if (!out) {
2786 return -ENOMEM;
2787 }
2788
Haynes Mathew George204045b2015-02-25 20:32:03 -08002789 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2790 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 if (devices == AUDIO_DEVICE_NONE)
2793 devices = AUDIO_DEVICE_OUT_SPEAKER;
2794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 out->flags = flags;
2796 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002797 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002798 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->sample_rate = config->sample_rate;
2800 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2801 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002802 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002803 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002804 out->non_blocking = 0;
2805 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302807 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2808 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002809 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2810 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2811
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002812 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002813 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2814 ret = read_hdmi_channel_masks(out);
2815
2816 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2817 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002818 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002819 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002820 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002821
2822 if (config->sample_rate == 0)
2823 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2824 if (config->channel_mask == 0)
2825 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2826
2827 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2830 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002832 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002834 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2835 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002836 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002837 ret = voice_extn_compress_voip_open_output_stream(out);
2838 if (ret != 0) {
2839 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2840 __func__, ret);
2841 goto error_open;
2842 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2844 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2845 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2846 ALOGE("%s: Unsupported Offload information", __func__);
2847 ret = -EINVAL;
2848 goto error_open;
2849 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002850
2851 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2852 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2853 ALOGV("read and update_pass through formats");
2854 ret = audio_extn_dolby_update_passt_formats(adev, out);
2855 if(ret != 0) {
2856 goto error_open;
2857 }
2858 if(config->offload_info.format == 0)
2859 config->offload_info.format = out->supported_formats[0];
2860 }
2861
Mingming Yin90310102013-11-13 16:57:00 -08002862 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002863 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 ALOGE("%s: Unsupported audio format", __func__);
2865 ret = -EINVAL;
2866 goto error_open;
2867 }
2868
2869 out->compr_config.codec = (struct snd_codec *)
2870 calloc(1, sizeof(struct snd_codec));
2871
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002872 if (!out->compr_config.codec) {
2873 ret = -ENOMEM;
2874 goto error_open;
2875 }
2876
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002877 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 if (config->offload_info.channel_mask)
2879 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002880 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002882 config->offload_info.channel_mask = config->channel_mask;
2883 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002884 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->sample_rate = config->offload_info.sample_rate;
2886
2887 out->stream.set_callback = out_set_callback;
2888 out->stream.pause = out_pause;
2889 out->stream.resume = out_resume;
2890 out->stream.drain = out_drain;
2891 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002892 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002894 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002895 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002896 audio_extn_dolby_get_snd_codec_id(adev, out,
2897 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002898 else
2899 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302901 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002902 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002903 platform_get_pcm_offload_buffer_size(&config->offload_info);
2904 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2905 out->compr_config.fragment_size =
2906 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 } else {
2908 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002909 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002910 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2912 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002913 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 out->compr_config.codec->bit_rate =
2915 config->offload_info.bit_rate;
2916 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002917 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302919 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002920 /*TODO: Do we need to change it for passthrough */
2921 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922
Mingming Yin3ee55c62014-08-04 14:23:35 -07002923 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2924 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002925 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2926 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002927 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002928 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2929
Mingming Yin3ee55c62014-08-04 14:23:35 -07002930 if (out->bit_width == 24) {
2931 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2932 }
2933
Amit Shekhar6f461b12014-08-01 14:52:58 -07002934 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302935 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002937 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2938 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002939
Sharad Sangleb27354b2015-06-18 15:58:55 +05302940 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002941 //this flag is set from framework only if its for PCM formats
2942 //no need to check for PCM format again
2943 out->non_blocking = 0;
2944 out->use_small_bufs = true;
2945 ALOGI("Keep write blocking for small buff: non_blockling %d",
2946 out->non_blocking);
2947 }
2948
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002949 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002950 out->offload_state = OFFLOAD_STATE_IDLE;
2951 out->playback_started = 0;
2952
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002953 audio_extn_dts_create_state_notifier_node(out->usecase);
2954
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 create_offload_callback_thread(out);
2956 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2957 __func__, config->offload_info.version,
2958 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002959 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002960 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002961 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2962 ret = voice_check_and_set_incall_music_usecase(adev, out);
2963 if (ret != 0) {
2964 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2965 __func__, ret);
2966 goto error_open;
2967 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002968 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2969 if (config->sample_rate == 0)
2970 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2971 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2972 config->sample_rate != 8000) {
2973 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2974 ret = -EINVAL;
2975 goto error_open;
2976 }
2977 out->sample_rate = config->sample_rate;
2978 out->config.rate = config->sample_rate;
2979 if (config->format == AUDIO_FORMAT_DEFAULT)
2980 config->format = AUDIO_FORMAT_PCM_16_BIT;
2981 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2982 config->format = AUDIO_FORMAT_PCM_16_BIT;
2983 ret = -EINVAL;
2984 goto error_open;
2985 }
2986 out->format = config->format;
2987 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2988 out->config = pcm_config_afe_proxy_playback;
2989 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002990 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002991 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2993 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002995 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2996 format = AUDIO_FORMAT_PCM_16_BIT;
2997 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2998 out->config = pcm_config_deep_buffer;
2999 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003000 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003001 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003002 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003003 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003004 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003005 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 }
3007
Amit Shekhar1d896042014-10-03 13:16:09 -07003008 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3009 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003010 /* TODO remove this hardcoding and check why width is zero*/
3011 if (out->bit_width == 0)
3012 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003013 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3014 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003015 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303016 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003017 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3018 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3019 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003020 if(adev->primary_output == NULL)
3021 adev->primary_output = out;
3022 else {
3023 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003024 ret = -EEXIST;
3025 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003026 }
3027 }
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 /* Check if this usecase is already existing */
3030 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003031 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3032 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003035 ret = -EEXIST;
3036 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 }
3038 pthread_mutex_unlock(&adev->lock);
3039
3040 out->stream.common.get_sample_rate = out_get_sample_rate;
3041 out->stream.common.set_sample_rate = out_set_sample_rate;
3042 out->stream.common.get_buffer_size = out_get_buffer_size;
3043 out->stream.common.get_channels = out_get_channels;
3044 out->stream.common.get_format = out_get_format;
3045 out->stream.common.set_format = out_set_format;
3046 out->stream.common.standby = out_standby;
3047 out->stream.common.dump = out_dump;
3048 out->stream.common.set_parameters = out_set_parameters;
3049 out->stream.common.get_parameters = out_get_parameters;
3050 out->stream.common.add_audio_effect = out_add_audio_effect;
3051 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3052 out->stream.get_latency = out_get_latency;
3053 out->stream.set_volume = out_set_volume;
3054 out->stream.write = out_write;
3055 out->stream.get_render_position = out_get_render_position;
3056 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003057 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003060 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003061 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062
3063 config->format = out->stream.common.get_format(&out->stream.common);
3064 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3065 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3066
3067 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303068 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3069 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003070
3071 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3072 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3073 popcount(out->channel_mask), out->playback_started);
3074
Eric Laurent994a6932013-07-17 11:51:42 -07003075 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003077
3078error_open:
3079 free(out);
3080 *stream_out = NULL;
3081 ALOGD("%s: exit: ret %d", __func__, ret);
3082 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083}
3084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003085static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 struct audio_stream_out *stream)
3087{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 struct stream_out *out = (struct stream_out *)stream;
3089 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003090 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303092 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3093
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003094 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303095 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003096 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303097 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003098 if(ret != 0)
3099 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3100 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003101 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003102 out_standby(&stream->common);
3103
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003104 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003105 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003107 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108 if (out->compr_config.codec != NULL)
3109 free(out->compr_config.codec);
3110 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003111
3112 if (adev->voice_tx_output == out)
3113 adev->voice_tx_output = NULL;
3114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003115 pthread_cond_destroy(&out->cond);
3116 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003118 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119}
3120
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003121static void close_compress_sessions(struct audio_device *adev)
3122{
Mingming Yin7b762e72015-03-04 13:47:32 -08003123 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303124 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003125 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003126 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303127
3128 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003129 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303130 if (is_offload_usecase(usecase->id)) {
3131 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003132 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3133 out = usecase->stream.out;
3134 pthread_mutex_unlock(&adev->lock);
3135 out_standby(&out->stream.common);
3136 pthread_mutex_lock(&adev->lock);
3137 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303138 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003139 }
3140 pthread_mutex_unlock(&adev->lock);
3141}
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3144{
3145 struct audio_device *adev = (struct audio_device *)dev;
3146 struct str_parms *parms;
3147 char *str;
3148 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003149 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003150 int ret;
3151 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003153 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303156 if (!parms)
3157 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3159 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303160 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303162 struct listnode *node;
3163 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303164 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003166 //close compress sessions on OFFLINE status
3167 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303168 } else if (strstr(snd_card_status, "ONLINE")) {
3169 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303170 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303171 if (!platform_is_acdb_initialized(adev->platform)) {
3172 ret = platform_acdb_init(adev->platform);
3173 if(ret)
3174 ALOGE("acdb initialization is failed");
3175
3176 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303177 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303178 }
3179
3180 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003181 status = voice_set_parameters(adev, parms);
3182 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003183 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003185 status = platform_set_parameters(adev->platform, parms);
3186 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003187 goto done;
3188
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003189 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3190 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003191 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3193 adev->bluetooth_nrec = true;
3194 else
3195 adev->bluetooth_nrec = false;
3196 }
3197
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3199 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3201 adev->screen_off = false;
3202 else
3203 adev->screen_off = true;
3204 }
3205
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 ret = str_parms_get_int(parms, "rotation", &val);
3207 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003208 bool reverse_speakers = false;
3209 switch(val) {
3210 // FIXME: note that the code below assumes that the speakers are in the correct placement
3211 // relative to the user when the device is rotated 90deg from its default rotation. This
3212 // assumption is device-specific, not platform-specific like this code.
3213 case 270:
3214 reverse_speakers = true;
3215 break;
3216 case 0:
3217 case 90:
3218 case 180:
3219 break;
3220 default:
3221 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003222 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003223 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003224 if (status == 0) {
3225 if (adev->speaker_lr_swap != reverse_speakers) {
3226 adev->speaker_lr_swap = reverse_speakers;
3227 // only update the selected device if there is active pcm playback
3228 struct audio_usecase *usecase;
3229 struct listnode *node;
3230 list_for_each(node, &adev->usecase_list) {
3231 usecase = node_to_item(node, struct audio_usecase, list);
3232 if (usecase->type == PCM_PLAYBACK) {
3233 select_devices(adev, usecase->id);
3234 break;
3235 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003236 }
3237 }
3238 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003239 }
3240
Mingming Yin514a8bc2014-07-29 15:22:21 -07003241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3242 if (ret >= 0) {
3243 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3244 adev->bt_wb_speech_enabled = true;
3245 else
3246 adev->bt_wb_speech_enabled = false;
3247 }
3248
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003249 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3250 if (ret >= 0) {
3251 val = atoi(value);
3252 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3253 ALOGV("cache new edid");
3254 platform_cache_edid(adev->platform);
3255 }
3256 }
3257
3258 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3259 if (ret >= 0) {
3260 val = atoi(value);
3261 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3262 ALOGV("invalidate cached edid");
3263 platform_invalidate_edid(adev->platform);
3264 }
3265 }
3266
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003267 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003268
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003269done:
3270 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003271 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303272error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003273 ALOGV("%s: exit with code(%d)", __func__, status);
3274 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
3277static char* adev_get_parameters(const struct audio_hw_device *dev,
3278 const char *keys)
3279{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003280 struct audio_device *adev = (struct audio_device *)dev;
3281 struct str_parms *reply = str_parms_create();
3282 struct str_parms *query = str_parms_create_str(keys);
3283 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303284 char value[256] = {0};
3285 int ret = 0;
3286
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003287 if (!query || !reply) {
3288 ALOGE("adev_get_parameters: failed to create query or reply");
3289 return NULL;
3290 }
3291
Naresh Tannirud7205b62014-06-20 02:54:48 +05303292 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3293 sizeof(value));
3294 if (ret >=0) {
3295 int val = 1;
3296 pthread_mutex_lock(&adev->snd_card_status.lock);
3297 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3298 val = 0;
3299 pthread_mutex_unlock(&adev->snd_card_status.lock);
3300 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3301 goto exit;
3302 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003303
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003304 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003305 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003306 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003307 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303308 pthread_mutex_unlock(&adev->lock);
3309
Naresh Tannirud7205b62014-06-20 02:54:48 +05303310exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003311 str = str_parms_to_str(reply);
3312 str_parms_destroy(query);
3313 str_parms_destroy(reply);
3314
3315 ALOGV("%s: exit: returns - %s", __func__, str);
3316 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003319static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320{
3321 return 0;
3322}
3323
3324static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3325{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003326 int ret;
3327 struct audio_device *adev = (struct audio_device *)dev;
3328 pthread_mutex_lock(&adev->lock);
3329 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003330 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003331 pthread_mutex_unlock(&adev->lock);
3332 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3336 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return -ENOSYS;
3339}
3340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003341static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3342 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return -ENOSYS;
3345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3348 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return -ENOSYS;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3354 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355{
3356 return -ENOSYS;
3357}
3358
3359static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3360{
3361 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 pthread_mutex_lock(&adev->lock);
3364 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003365 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003367 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3368 voice_is_in_call(adev)) {
3369 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303370 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003371 adev->current_call_output = NULL;
3372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 }
3374 pthread_mutex_unlock(&adev->lock);
3375 return 0;
3376}
3377
3378static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3379{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003380 int ret;
3381
3382 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003383 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003384 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3385 pthread_mutex_unlock(&adev->lock);
3386
3387 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388}
3389
3390static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3391{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003392 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 return 0;
3394}
3395
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003396static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 const struct audio_config *config)
3398{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003399 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003401 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3402 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403}
3404
3405static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003406 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407 audio_devices_t devices,
3408 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003409 struct audio_stream_in **stream_in,
3410 audio_input_flags_t flags __unused,
3411 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003412 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413{
3414 struct audio_device *adev = (struct audio_device *)dev;
3415 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003416 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003417 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003418 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 *stream_in = NULL;
3421 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3422 return -EINVAL;
3423
3424 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003425
3426 if (!in) {
3427 ALOGE("failed to allocate input stream");
3428 return -ENOMEM;
3429 }
3430
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303431 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003432 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3433 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003435 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 in->stream.common.get_sample_rate = in_get_sample_rate;
3438 in->stream.common.set_sample_rate = in_set_sample_rate;
3439 in->stream.common.get_buffer_size = in_get_buffer_size;
3440 in->stream.common.get_channels = in_get_channels;
3441 in->stream.common.get_format = in_get_format;
3442 in->stream.common.set_format = in_set_format;
3443 in->stream.common.standby = in_standby;
3444 in->stream.common.dump = in_dump;
3445 in->stream.common.set_parameters = in_set_parameters;
3446 in->stream.common.get_parameters = in_get_parameters;
3447 in->stream.common.add_audio_effect = in_add_audio_effect;
3448 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3449 in->stream.set_gain = in_set_gain;
3450 in->stream.read = in_read;
3451 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3452
3453 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003454 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 in->standby = 1;
3457 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003458 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459
3460 /* Update config params with the requested sample rate and channels */
3461 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003462 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3463 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3464 is_low_latency = true;
3465#if LOW_LATENCY_CAPTURE_USE_CASE
3466 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3467#endif
3468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003471 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003473 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303474 if (adev->mode != AUDIO_MODE_IN_CALL) {
3475 ret = -EINVAL;
3476 goto err_open;
3477 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003478 if (config->sample_rate == 0)
3479 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3480 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3481 config->sample_rate != 8000) {
3482 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3483 ret = -EINVAL;
3484 goto err_open;
3485 }
3486 if (config->format == AUDIO_FORMAT_DEFAULT)
3487 config->format = AUDIO_FORMAT_PCM_16_BIT;
3488 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3489 config->format = AUDIO_FORMAT_PCM_16_BIT;
3490 ret = -EINVAL;
3491 goto err_open;
3492 }
3493
3494 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3495 in->config = pcm_config_afe_proxy_record;
3496 in->config.channels = channel_count;
3497 in->config.rate = config->sample_rate;
3498 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003499 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003500 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003501 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3502 ret = -EINVAL;
3503 goto err_open;
3504 }
3505 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003506 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003507 }
Mingming Yine62d7842013-10-25 16:26:03 -07003508 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003509 audio_extn_compr_cap_format_supported(config->format) &&
3510 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003511 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003512 } else {
3513 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003514 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003515 buffer_size = get_input_buffer_size(config->sample_rate,
3516 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003517 channel_count,
3518 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003519 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003520 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3521 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3522 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3523 (in->config.rate == 8000 || in->config.rate == 16000) &&
3524 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3525 voice_extn_compress_voip_open_input_stream(in);
3526 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003529 /* This stream could be for sound trigger lab,
3530 get sound trigger pcm if present */
3531 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303532 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003535 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003536 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537
3538err_open:
3539 free(in);
3540 *stream_in = NULL;
3541 return ret;
3542}
3543
3544static void adev_close_input_stream(struct audio_hw_device *dev,
3545 struct audio_stream_in *stream)
3546{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003547 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003548 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003549 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303550
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303551 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003552
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303553 /* Disable echo reference while closing input stream */
3554 platform_set_echo_reference(adev->platform, false);
3555
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003556 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303557 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003558 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303559 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003560 if (ret != 0)
3561 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3562 __func__, ret);
3563 } else
3564 in_standby(&stream->common);
3565
Mingming Yin7b762e72015-03-04 13:47:32 -08003566 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003567 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003568 audio_extn_ssr_deinit();
3569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570
Mingming Yine62d7842013-10-25 16:26:03 -07003571 if(audio_extn_compr_cap_enabled() &&
3572 audio_extn_compr_cap_format_supported(in->config.format))
3573 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003574
3575 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 return;
3577}
3578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003579static int adev_dump(const audio_hw_device_t *device __unused,
3580 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581{
3582 return 0;
3583}
3584
3585static int adev_close(hw_device_t *device)
3586{
3587 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003588
3589 if (!adev)
3590 return 0;
3591
3592 pthread_mutex_lock(&adev_init_lock);
3593
3594 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003595 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003596 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003597 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003598 audio_route_free(adev->audio_route);
3599 free(adev->snd_dev_ref_cnt);
3600 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003601 free(device);
3602 adev = NULL;
3603 }
3604 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 return 0;
3606}
3607
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003608/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3609 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3610 * just that it _might_ work.
3611 */
3612static int period_size_is_plausible_for_low_latency(int period_size)
3613{
3614 switch (period_size) {
3615 case 160:
3616 case 240:
3617 case 320:
3618 case 480:
3619 return 1;
3620 default:
3621 return 0;
3622 }
3623}
3624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625static int adev_open(const hw_module_t *module, const char *name,
3626 hw_device_t **device)
3627{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003628 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003630 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3632
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003633 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003634 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003635 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003636 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003637 ALOGD("%s: returning existing instance of adev", __func__);
3638 ALOGD("%s: exit", __func__);
3639 pthread_mutex_unlock(&adev_init_lock);
3640 return 0;
3641 }
3642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 adev = calloc(1, sizeof(struct audio_device));
3644
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003645 if (!adev) {
3646 pthread_mutex_unlock(&adev_init_lock);
3647 return -ENOMEM;
3648 }
3649
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003650 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3653 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3654 adev->device.common.module = (struct hw_module_t *)module;
3655 adev->device.common.close = adev_close;
3656
3657 adev->device.init_check = adev_init_check;
3658 adev->device.set_voice_volume = adev_set_voice_volume;
3659 adev->device.set_master_volume = adev_set_master_volume;
3660 adev->device.get_master_volume = adev_get_master_volume;
3661 adev->device.set_master_mute = adev_set_master_mute;
3662 adev->device.get_master_mute = adev_get_master_mute;
3663 adev->device.set_mode = adev_set_mode;
3664 adev->device.set_mic_mute = adev_set_mic_mute;
3665 adev->device.get_mic_mute = adev_get_mic_mute;
3666 adev->device.set_parameters = adev_set_parameters;
3667 adev->device.get_parameters = adev_get_parameters;
3668 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3669 adev->device.open_output_stream = adev_open_output_stream;
3670 adev->device.close_output_stream = adev_close_output_stream;
3671 adev->device.open_input_stream = adev_open_input_stream;
3672 adev->device.close_input_stream = adev_close_input_stream;
3673 adev->device.dump = adev_dump;
3674
3675 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003677 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003678 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003681 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003682 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003683 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003684 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003685 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003686 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003687 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303688 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303689
3690 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3691 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003693 adev->platform = platform_init(adev);
3694 if (!adev->platform) {
3695 free(adev->snd_dev_ref_cnt);
3696 free(adev);
3697 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3698 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003699 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003700 return -EINVAL;
3701 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003702
Naresh Tanniru4c630392014-05-12 01:05:52 +05303703 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3704
Eric Laurentc4aef752013-09-12 17:45:53 -07003705 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3706 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3707 if (adev->visualizer_lib == NULL) {
3708 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3709 } else {
3710 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3711 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003712 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003713 "visualizer_hal_start_output");
3714 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003715 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003716 "visualizer_hal_stop_output");
3717 }
3718 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003719 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003720 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003721
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003722 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3723 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3724 if (adev->offload_effects_lib == NULL) {
3725 ALOGE("%s: DLOPEN failed for %s", __func__,
3726 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3727 } else {
3728 ALOGV("%s: DLOPEN successful for %s", __func__,
3729 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3730 adev->offload_effects_start_output =
3731 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3732 "offload_effects_bundle_hal_start_output");
3733 adev->offload_effects_stop_output =
3734 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3735 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003736 adev->offload_effects_set_hpx_state =
3737 (int (*)(bool))dlsym(adev->offload_effects_lib,
3738 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003739 }
3740 }
3741
Mingming Yin514a8bc2014-07-29 15:22:21 -07003742 adev->bt_wb_speech_enabled = false;
3743
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003744 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 *device = &adev->device.common;
3746
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003747 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3748 &adev->streams_output_cfg_list);
3749
Kiran Kandi910e1862013-10-29 13:29:42 -07003750 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003751
3752 char value[PROPERTY_VALUE_MAX];
3753 int trial;
3754 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3755 trial = atoi(value);
3756 if (period_size_is_plausible_for_low_latency(trial)) {
3757 pcm_config_low_latency.period_size = trial;
3758 pcm_config_low_latency.start_threshold = trial / 4;
3759 pcm_config_low_latency.avail_min = trial / 4;
3760 configured_low_latency_capture_period_size = trial;
3761 }
3762 }
3763 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3764 trial = atoi(value);
3765 if (period_size_is_plausible_for_low_latency(trial)) {
3766 configured_low_latency_capture_period_size = trial;
3767 }
3768 }
3769
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003770 pthread_mutex_unlock(&adev_init_lock);
3771
Eric Laurent994a6932013-07-17 11:51:42 -07003772 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 return 0;
3774}
3775
3776static struct hw_module_methods_t hal_module_methods = {
3777 .open = adev_open,
3778};
3779
3780struct audio_module HAL_MODULE_INFO_SYM = {
3781 .common = {
3782 .tag = HARDWARE_MODULE_TAG,
3783 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3784 .hal_api_version = HARDWARE_HAL_API_VERSION,
3785 .id = AUDIO_HARDWARE_MODULE_ID,
3786 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003787 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 .methods = &hal_module_methods,
3789 },
3790};