blob: e4c8cad608e026737e744926e8b31ef2c1c91314 [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 ||
Manish Dewangan93672f12015-08-24 20:30:31 +0530288 format == AUDIO_FORMAT_AAC_ADTS_LC ||
289 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
290 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800291 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700292 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800293 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530294 format == AUDIO_FORMAT_ALAC ||
295 format == AUDIO_FORMAT_APE ||
296 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800297 format == AUDIO_FORMAT_WMA ||
298 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800299 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700300
301 return false;
302}
303
304static int get_snd_codec_id(audio_format_t format)
305{
306 int id = 0;
307
Ashish Jainf9b78162014-08-25 20:36:25 +0530308 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700309 case AUDIO_FORMAT_MP3:
310 id = SND_AUDIOCODEC_MP3;
311 break;
312 case AUDIO_FORMAT_AAC:
313 id = SND_AUDIOCODEC_AAC;
314 break;
Manish Dewangan93672f12015-08-24 20:30:31 +0530315 case AUDIO_FORMAT_AAC_ADTS:
316 id = SND_AUDIOCODEC_AAC;
317 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530318 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 id = SND_AUDIOCODEC_PCM;
320 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700321 case AUDIO_FORMAT_FLAC:
322 id = SND_AUDIOCODEC_FLAC;
323 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530324 case AUDIO_FORMAT_ALAC:
325 id = SND_AUDIOCODEC_ALAC;
326 break;
327 case AUDIO_FORMAT_APE:
328 id = SND_AUDIOCODEC_APE;
329 break;
330 case AUDIO_FORMAT_VORBIS:
331 id = SND_AUDIOCODEC_VORBIS;
332 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800333 case AUDIO_FORMAT_WMA:
334 id = SND_AUDIOCODEC_WMA;
335 break;
336 case AUDIO_FORMAT_WMA_PRO:
337 id = SND_AUDIOCODEC_WMA_PRO;
338 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700339 default:
Mingming Yin90310102013-11-13 16:57:00 -0800340 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700341 }
342
343 return id;
344}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800345
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530346int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530347{
348 int snd_scard_state;
349
350 if (!adev)
351 return SND_CARD_STATE_OFFLINE;
352
353 pthread_mutex_lock(&adev->snd_card_status.lock);
354 snd_scard_state = adev->snd_card_status.state;
355 pthread_mutex_unlock(&adev->snd_card_status.lock);
356
357 return snd_scard_state;
358}
359
360static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
361{
362 if (!adev)
363 return -ENOSYS;
364
365 pthread_mutex_lock(&adev->snd_card_status.lock);
366 adev->snd_card_status.state = snd_scard_state;
367 pthread_mutex_unlock(&adev->snd_card_status.lock);
368
369 return 0;
370}
371
Avinash Vaish71a8b972014-07-24 15:36:33 +0530372static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
373 struct audio_usecase *uc_info)
374{
375 struct listnode *node;
376 struct audio_usecase *usecase;
377
378 if (uc_info == NULL)
379 return -EINVAL;
380
381 /* Re-route all voice usecases on the shared backend other than the
382 specified usecase to new snd devices */
383 list_for_each(node, &adev->usecase_list) {
384 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800385 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530386 enable_audio_route(adev, usecase);
387 }
388 return 0;
389}
390
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700391int pcm_ioctl(struct pcm *pcm, int request, ...)
392{
393 va_list ap;
394 void * arg;
395 int pcm_fd = *(int*)pcm;
396
397 va_start(ap, request);
398 arg = va_arg(ap, void *);
399 va_end(ap);
400
401 return ioctl(pcm_fd, request, arg);
402}
403
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700404int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700405 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800406{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700407 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700408 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409
410 if (usecase == NULL)
411 return -EINVAL;
412
413 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
414
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800415 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700416 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800417 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700418 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800419
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800420#ifdef DS1_DOLBY_DAP_ENABLED
421 audio_extn_dolby_set_dmid(adev);
422 audio_extn_dolby_set_endpoint(adev);
423#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700424 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700425 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530426 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700427 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530428 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800429 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530430 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700431 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
432 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433 ALOGV("%s: exit", __func__);
434 return 0;
435}
436
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700437int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700438 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700441 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800442
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530443 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800444 return -EINVAL;
445
446 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 if (usecase->type == PCM_CAPTURE)
448 snd_device = usecase->in_snd_device;
449 else
450 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800451 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530452 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700453 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
454 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700455 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530456 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700461int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700464 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
465
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800466 if (snd_device < SND_DEVICE_MIN ||
467 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800468 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800469 return -EINVAL;
470 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471
472 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700473
474 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
475 ALOGE("%s: Invalid sound device returned", __func__);
476 return -EINVAL;
477 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700478 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700479 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700480 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700481 return 0;
482 }
483
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700484 if (audio_extn_spkr_prot_is_enabled())
485 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700486 /* start usb playback thread */
487 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
488 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
489 audio_extn_usb_start_playback(adev);
490
491 /* start usb capture thread */
492 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
493 audio_extn_usb_start_capture(adev);
494
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530495 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530496 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700498 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700499 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
500 adev->snd_dev_ref_cnt[snd_device]--;
501 return -EINVAL;
502 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200503 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800504 if (audio_extn_spkr_prot_start_processing(snd_device)) {
505 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200506 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800507 return -EINVAL;
508 }
509 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700510 ALOGV("%s: snd_device(%d: %s)", __func__,
511 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700512 /* due to the possibility of calibration overwrite between listen
513 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700518 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700519 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700520 audio_extn_sound_trigger_update_device_status(snd_device,
521 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530522 audio_extn_listen_update_device_status(snd_device,
523 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700524 return -EINVAL;
525 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300526 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700527 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529 return 0;
530}
531
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700532int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700533 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700535 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
536
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800537 if (snd_device < SND_DEVICE_MIN ||
538 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800539 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800540 return -EINVAL;
541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
543 ALOGE("%s: device ref cnt is already 0", __func__);
544 return -EINVAL;
545 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700548
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
550 ALOGE("%s: Invalid sound device returned", __func__);
551 return -EINVAL;
552 }
553
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700555 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700556 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800557 /* exit usb play back thread */
558 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
559 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
560 audio_extn_usb_stop_playback();
561
562 /* exit usb capture thread */
563 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700564 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800565
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530566 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530567 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800568 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700569 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700570 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300571 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700572 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300573 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700574
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530575 if (snd_device == SND_DEVICE_OUT_HDMI)
576 adev->mChannelStatusSet = false;
577
Linux Build Service Account75e43952015-08-26 19:58:56 -0700578 if (snd_device == SND_DEVICE_OUT_HDMI)
579 adev->mChannelStatusSet = false;
580
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200581 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700582 audio_extn_sound_trigger_update_device_status(snd_device,
583 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530584 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800585 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588 return 0;
589}
590
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700591static void check_usecases_codec_backend(struct audio_device *adev,
592 struct audio_usecase *uc_info,
593 snd_device_t snd_device)
594{
595 struct listnode *node;
596 struct audio_usecase *usecase;
597 bool switch_device[AUDIO_USECASE_MAX];
598 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530599 int backend_idx = DEFAULT_CODEC_BACKEND;
600 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601
602 /*
603 * This function is to make sure that all the usecases that are active on
604 * the hardware codec backend are always routed to any one device that is
605 * handled by the hardware codec.
606 * For example, if low-latency and deep-buffer usecases are currently active
607 * on speaker and out_set_parameters(headset) is received on low-latency
608 * output, then we have to make sure deep-buffer is also switched to headset,
609 * because of the limitation that both the devices cannot be enabled
610 * at the same time as they share the same backend.
611 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700612 /*
613 * This call is to check if we need to force routing for a particular stream
614 * If there is a backend configuration change for the device when a
615 * new stream starts, then ADM needs to be closed and re-opened with the new
616 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530617 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700618 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530619 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
620 snd_device);
621 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800623 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800624 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 for (i = 0; i < AUDIO_USECASE_MAX; i++)
626 switch_device[i] = false;
627
628 list_for_each(node, &adev->usecase_list) {
629 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530630
631 if (usecase == uc_info)
632 continue;
633 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
634 ALOGV("%s: backend_idx: %d,"
635 "usecase_backend_idx: %d, curr device: %s, usecase device:"
636 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530637 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530638
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800639 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700640 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530641 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
642 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530643 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530644 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700645 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700646 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 switch_device[usecase->id] = true;
648 num_uc_to_switch++;
649 }
650 }
651
652 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700653 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700654
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530655 /* Make sure the previous devices to be disabled first and then enable the
656 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 list_for_each(node, &adev->usecase_list) {
658 usecase = node_to_item(node, struct audio_usecase, list);
659 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700660 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661 }
662 }
663
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700664 list_for_each(node, &adev->usecase_list) {
665 usecase = node_to_item(node, struct audio_usecase, list);
666 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700667 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700668 }
669 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 /* Re-route all the usecases on the shared backend other than the
672 specified usecase to new snd devices */
673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530675 /* Update the out_snd_device only before enabling the audio route */
676 if (switch_device[usecase->id] ) {
677 usecase->out_snd_device = snd_device;
678 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530679 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 }
681 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 }
683}
684
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700685static void check_and_route_capture_usecases(struct audio_device *adev,
686 struct audio_usecase *uc_info,
687 snd_device_t snd_device)
688{
689 struct listnode *node;
690 struct audio_usecase *usecase;
691 bool switch_device[AUDIO_USECASE_MAX];
692 int i, num_uc_to_switch = 0;
693
694 /*
695 * This function is to make sure that all the active capture usecases
696 * are always routed to the same input sound device.
697 * For example, if audio-record and voice-call usecases are currently
698 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
699 * is received for voice call then we have to make sure that audio-record
700 * usecase is also switched to earpiece i.e. voice-dmic-ef,
701 * because of the limitation that two devices cannot be enabled
702 * at the same time if they share the same backend.
703 */
704 for (i = 0; i < AUDIO_USECASE_MAX; i++)
705 switch_device[i] = false;
706
707 list_for_each(node, &adev->usecase_list) {
708 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800709 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700711 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700712 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530713 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
714 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700715 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700716 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
717 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700718 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700719 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700720 switch_device[usecase->id] = true;
721 num_uc_to_switch++;
722 }
723 }
724
725 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700726 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530728 /* Make sure the previous devices to be disabled first and then enable the
729 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700733 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800734 }
735 }
736
737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700741 }
742 }
743
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744 /* Re-route all the usecases on the shared backend other than the
745 specified usecase to new snd devices */
746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
748 /* Update the in_snd_device only before enabling the audio route */
749 if (switch_device[usecase->id] ) {
750 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800751 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530752 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700753 }
754 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700755 }
756}
757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700759static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700762 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763
764 switch (channels) {
765 /*
766 * Do not handle stereo output in Multi-channel cases
767 * Stereo case is handled in normal playback path
768 */
769 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700770 ALOGV("%s: HDMI supports Quad and 5.1", __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;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 break;
777 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700778 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800785 break;
786 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700787 ALOGE("HDMI does not support multi channel playback");
788 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 break;
790 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792}
793
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800794audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
795 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700796{
797 struct audio_usecase *usecase;
798 struct listnode *node;
799
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800802 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803 ALOGV("%s: usecase id %d", __func__, usecase->id);
804 return usecase->id;
805 }
806 }
807 return USECASE_INVALID;
808}
809
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700810struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700811 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812{
813 struct audio_usecase *usecase;
814 struct listnode *node;
815
816 list_for_each(node, &adev->usecase_list) {
817 usecase = node_to_item(node, struct audio_usecase, list);
818 if (usecase->id == uc_id)
819 return usecase;
820 }
821 return NULL;
822}
823
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700824int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800826 snd_device_t out_snd_device = SND_DEVICE_NONE;
827 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 struct audio_usecase *usecase = NULL;
829 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800830 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800831 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800832 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800833 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 usecase = get_usecase_from_list(adev, uc_id);
837 if (usecase == NULL) {
838 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
839 return -EINVAL;
840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800842 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800843 (usecase->type == VOIP_CALL) ||
844 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700845 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800846 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700847 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848 usecase->devices = usecase->stream.out->devices;
849 } else {
850 /*
851 * If the voice call is active, use the sound devices of voice call usecase
852 * so that it would not result any device switch. All the usecases will
853 * be switched to new device when select_devices() is called for voice call
854 * usecase. This is to avoid switching devices for voice call when
855 * check_usecases_codec_backend() is called below.
856 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700857 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700858 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800859 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
861 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 in_snd_device = vc_usecase->in_snd_device;
863 out_snd_device = vc_usecase->out_snd_device;
864 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800865 } else if (voice_extn_compress_voip_is_active(adev)) {
866 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530868 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700869 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800870 in_snd_device = voip_usecase->in_snd_device;
871 out_snd_device = voip_usecase->out_snd_device;
872 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800873 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800874 hfp_ucid = audio_extn_hfp_get_usecase();
875 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800877 in_snd_device = hfp_usecase->in_snd_device;
878 out_snd_device = hfp_usecase->out_snd_device;
879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 }
881 if (usecase->type == PCM_PLAYBACK) {
882 usecase->devices = usecase->stream.out->devices;
883 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700884 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700885 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800886 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700887 if (usecase->stream.out == adev->primary_output &&
888 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800889 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 select_devices(adev, adev->active_input->usecase);
891 }
892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 } else if (usecase->type == PCM_CAPTURE) {
894 usecase->devices = usecase->stream.in->device;
895 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700896 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700897 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530898 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
899 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
900 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
901 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700902 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800903 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700904 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
905 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700907 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 }
910 }
911
912 if (out_snd_device == usecase->out_snd_device &&
913 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800914 return 0;
915 }
916
sangwoobc677242013-08-08 16:53:43 +0900917 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700918 out_snd_device, platform_get_snd_device_name(out_snd_device),
919 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 /*
922 * Limitation: While in call, to do a device switch we need to disable
923 * and enable both RX and TX devices though one of them is same as current
924 * device.
925 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700926 if ((usecase->type == VOICE_CALL) &&
927 (usecase->in_snd_device != SND_DEVICE_NONE) &&
928 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700929 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700930 }
931
932 if (((usecase->type == VOICE_CALL) ||
933 (usecase->type == VOIP_CALL)) &&
934 (usecase->out_snd_device != SND_DEVICE_NONE)) {
935 /* Disable sidetone only if voice/voip call already exists */
936 if (voice_is_call_state_active(adev) ||
937 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700938 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800939 }
940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 /* Disable current sound devices */
942 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700943 disable_audio_route(adev, usecase);
944 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945 }
946
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700948 disable_audio_route(adev, usecase);
949 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800950 }
951
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800952 /* Applicable only on the targets that has external modem.
953 * New device information should be sent to modem before enabling
954 * the devices to reduce in-call device switch time.
955 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700956 if ((usecase->type == VOICE_CALL) &&
957 (usecase->in_snd_device != SND_DEVICE_NONE) &&
958 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800959 status = platform_switch_voice_call_enable_device_config(adev->platform,
960 out_snd_device,
961 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700962 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800963
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 /* Enable new sound devices */
965 if (out_snd_device != SND_DEVICE_NONE) {
966 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
967 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700968 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969 }
970
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700971 if (in_snd_device != SND_DEVICE_NONE) {
972 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700973 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975
Avinash Vaish71a8b972014-07-24 15:36:33 +0530976 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700977 status = platform_switch_voice_call_device_post(adev->platform,
978 out_snd_device,
979 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530980 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700981 /* Enable sidetone only if voice/voip call already exists */
982 if (voice_is_call_state_active(adev) ||
983 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700984 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530985 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800986
sangwoo170731f2013-06-08 15:36:36 +0900987 usecase->in_snd_device = in_snd_device;
988 usecase->out_snd_device = out_snd_device;
989
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530990 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700991 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530992 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700993 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530994 usecase->stream.out->flags,
995 usecase->stream.out->format,
996 usecase->stream.out->sample_rate,
997 usecase->stream.out->bit_width,
998 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700999 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301000 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001001
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001002 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001003
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001004 /* Applicable only on the targets that has external modem.
1005 * Enable device command should be sent to modem only after
1006 * enabling voice call mixer controls
1007 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001008 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001009 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1010 out_snd_device,
1011 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301012 ALOGD("%s: done",__func__);
1013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 return status;
1015}
1016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017static int stop_input_stream(struct stream_in *in)
1018{
1019 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 struct audio_usecase *uc_info;
1021 struct audio_device *adev = in->dev;
1022
Eric Laurentc8400632013-02-14 19:04:54 -08001023 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024
Eric Laurent994a6932013-07-17 11:51:42 -07001025 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 uc_info = get_usecase_from_list(adev, in->usecase);
1028 if (uc_info == NULL) {
1029 ALOGE("%s: Could not find the usecase (%d) in the list",
1030 __func__, in->usecase);
1031 return -EINVAL;
1032 }
1033
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001034 /* Close in-call recording streams */
1035 voice_check_and_stop_incall_rec_usecase(adev, in);
1036
Eric Laurent150dbfe2013-02-27 14:31:02 -08001037 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001038 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039
1040 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001043 list_remove(&uc_info->list);
1044 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045
Eric Laurent994a6932013-07-17 11:51:42 -07001046 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 return ret;
1048}
1049
1050int start_input_stream(struct stream_in *in)
1051{
1052 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001053 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 struct audio_usecase *uc_info;
1055 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301056 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301058 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1059 if (get_usecase_from_list(adev, usecase) == NULL)
1060 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301061 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1062 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001063
Naresh Tanniru80659832014-06-04 18:17:56 +05301064
1065 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301066 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301067 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301068 goto error_config;
1069 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301070
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001071 /* Check if source matches incall recording usecase criteria */
1072 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1073 if (ret)
1074 goto error_config;
1075 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301076 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1077
1078 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1079 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1080 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1081 goto error_config;
1082 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001083
Eric Laurentb23d5282013-05-14 15:27:20 -07001084 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 if (in->pcm_device_id < 0) {
1086 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1087 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001088 ret = -EINVAL;
1089 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091
1092 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001094
1095 if (!uc_info) {
1096 ret = -ENOMEM;
1097 goto error_config;
1098 }
1099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 uc_info->id = in->usecase;
1101 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001102 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 uc_info->devices = in->device;
1104 uc_info->in_snd_device = SND_DEVICE_NONE;
1105 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001107 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301108 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110
Eric Laurentc8400632013-02-14 19:04:54 -08001111 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001112 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1113
1114 unsigned int flags = PCM_IN;
1115 unsigned int pcm_open_retry_count = 0;
1116
1117 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1118 flags |= PCM_MMAP | PCM_NOIRQ;
1119 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1120 }
1121
1122 while (1) {
1123 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1124 flags, &in->config);
1125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1126 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1127 if (in->pcm != NULL) {
1128 pcm_close(in->pcm);
1129 in->pcm = NULL;
1130 }
1131 if (pcm_open_retry_count-- == 0) {
1132 ret = -EIO;
1133 goto error_open;
1134 }
1135 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1136 continue;
1137 }
1138 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301140 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301141
Eric Laurent994a6932013-07-17 11:51:42 -07001142 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001143 return ret;
1144
1145error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301147 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001148
1149error_config:
1150 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001152
1153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154}
1155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001156/* must be called with out->lock locked */
1157static int send_offload_cmd_l(struct stream_out* out, int command)
1158{
1159 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1160
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001161 if (!cmd) {
1162 ALOGE("failed to allocate mem for command 0x%x", command);
1163 return -ENOMEM;
1164 }
1165
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001166 ALOGVV("%s %d", __func__, command);
1167
1168 cmd->cmd = command;
1169 list_add_tail(&out->offload_cmd_list, &cmd->node);
1170 pthread_cond_signal(&out->offload_cond);
1171 return 0;
1172}
1173
1174/* must be called iwth out->lock locked */
1175static void stop_compressed_output_l(struct stream_out *out)
1176{
1177 out->offload_state = OFFLOAD_STATE_IDLE;
1178 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001179 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001180 if (out->compr != NULL) {
1181 compress_stop(out->compr);
1182 while (out->offload_thread_blocked) {
1183 pthread_cond_wait(&out->cond, &out->lock);
1184 }
1185 }
1186}
1187
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001188bool is_offload_usecase(audio_usecase_t uc_id)
1189{
1190 unsigned int i;
1191 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1192 if (uc_id == offload_usecases[i])
1193 return true;
1194 }
1195 return false;
1196}
1197
1198static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1199{
1200 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1201 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1202 char value[PROPERTY_VALUE_MAX] = {0};
1203
1204 property_get("audio.offload.multiple.enabled", value, NULL);
1205 if (!(atoi(value) || !strncmp("true", value, 4)))
1206 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1207
1208 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1209 for (i = 0; i < num_usecase; i++) {
1210 if (!(adev->offload_usecases_state & (0x1<<i))) {
1211 adev->offload_usecases_state |= 0x1 << i;
1212 ret = offload_usecases[i];
1213 break;
1214 }
1215 }
1216 ALOGV("%s: offload usecase is %d", __func__, ret);
1217 return ret;
1218}
1219
1220static void free_offload_usecase(struct audio_device *adev,
1221 audio_usecase_t uc_id)
1222{
1223 unsigned int i;
1224 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1225 if (offload_usecases[i] == uc_id) {
1226 adev->offload_usecases_state &= ~(0x1<<i);
1227 break;
1228 }
1229 }
1230 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1231}
1232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233static void *offload_thread_loop(void *context)
1234{
1235 struct stream_out *out = (struct stream_out *) context;
1236 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001237 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1240 set_sched_policy(0, SP_FOREGROUND);
1241 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1242
1243 ALOGV("%s", __func__);
1244 pthread_mutex_lock(&out->lock);
1245 for (;;) {
1246 struct offload_cmd *cmd = NULL;
1247 stream_callback_event_t event;
1248 bool send_callback = false;
1249
1250 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1251 __func__, list_empty(&out->offload_cmd_list),
1252 out->offload_state);
1253 if (list_empty(&out->offload_cmd_list)) {
1254 ALOGV("%s SLEEPING", __func__);
1255 pthread_cond_wait(&out->offload_cond, &out->lock);
1256 ALOGV("%s RUNNING", __func__);
1257 continue;
1258 }
1259
1260 item = list_head(&out->offload_cmd_list);
1261 cmd = node_to_item(item, struct offload_cmd, node);
1262 list_remove(item);
1263
1264 ALOGVV("%s STATE %d CMD %d out->compr %p",
1265 __func__, out->offload_state, cmd->cmd, out->compr);
1266
1267 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1268 free(cmd);
1269 break;
1270 }
1271
1272 if (out->compr == NULL) {
1273 ALOGE("%s: Compress handle is NULL", __func__);
1274 pthread_cond_signal(&out->cond);
1275 continue;
1276 }
1277 out->offload_thread_blocked = true;
1278 pthread_mutex_unlock(&out->lock);
1279 send_callback = false;
1280 switch(cmd->cmd) {
1281 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001282 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001283 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001284 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001285 send_callback = true;
1286 event = STREAM_CBK_EVENT_WRITE_READY;
1287 break;
1288 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001289 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301290 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301292 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001293 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301294 if (ret < 0)
1295 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301296 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301297 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001298 compress_drain(out->compr);
1299 else
1300 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301301 if (ret != -ENETRESET) {
1302 send_callback = true;
1303 event = STREAM_CBK_EVENT_DRAIN_READY;
1304 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1305 } else
1306 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 break;
1308 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001309 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001311 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 send_callback = true;
1313 event = STREAM_CBK_EVENT_DRAIN_READY;
1314 break;
1315 default:
1316 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1317 break;
1318 }
1319 pthread_mutex_lock(&out->lock);
1320 out->offload_thread_blocked = false;
1321 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001322 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001323 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001325 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001326 free(cmd);
1327 }
1328
1329 pthread_cond_signal(&out->cond);
1330 while (!list_empty(&out->offload_cmd_list)) {
1331 item = list_head(&out->offload_cmd_list);
1332 list_remove(item);
1333 free(node_to_item(item, struct offload_cmd, node));
1334 }
1335 pthread_mutex_unlock(&out->lock);
1336
1337 return NULL;
1338}
1339
1340static int create_offload_callback_thread(struct stream_out *out)
1341{
1342 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1343 list_init(&out->offload_cmd_list);
1344 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1345 offload_thread_loop, out);
1346 return 0;
1347}
1348
1349static int destroy_offload_callback_thread(struct stream_out *out)
1350{
1351 pthread_mutex_lock(&out->lock);
1352 stop_compressed_output_l(out);
1353 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1354
1355 pthread_mutex_unlock(&out->lock);
1356 pthread_join(out->offload_thread, (void **) NULL);
1357 pthread_cond_destroy(&out->offload_cond);
1358
1359 return 0;
1360}
1361
Eric Laurent07eeafd2013-10-06 12:52:49 -07001362static bool allow_hdmi_channel_config(struct audio_device *adev)
1363{
1364 struct listnode *node;
1365 struct audio_usecase *usecase;
1366 bool ret = true;
1367
1368 list_for_each(node, &adev->usecase_list) {
1369 usecase = node_to_item(node, struct audio_usecase, list);
1370 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1371 /*
1372 * If voice call is already existing, do not proceed further to avoid
1373 * disabling/enabling both RX and TX devices, CSD calls, etc.
1374 * Once the voice call done, the HDMI channels can be configured to
1375 * max channels of remaining use cases.
1376 */
1377 if (usecase->id == USECASE_VOICE_CALL) {
1378 ALOGD("%s: voice call is active, no change in HDMI channels",
1379 __func__);
1380 ret = false;
1381 break;
1382 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1383 ALOGD("%s: multi channel playback is active, "
1384 "no change in HDMI channels", __func__);
1385 ret = false;
1386 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001387 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001388 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001389 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1390 ", no change in HDMI channels", __func__,
1391 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001392 ret = false;
1393 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 }
1395 }
1396 }
1397 return ret;
1398}
1399
1400static int check_and_set_hdmi_channels(struct audio_device *adev,
1401 unsigned int channels)
1402{
1403 struct listnode *node;
1404 struct audio_usecase *usecase;
1405
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001406 unsigned int supported_channels = platform_edid_get_max_channels(
1407 adev->platform);
1408 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001409 /* Check if change in HDMI channel config is allowed */
1410 if (!allow_hdmi_channel_config(adev))
1411 return 0;
1412
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001413 if (channels > supported_channels)
1414 channels = supported_channels;
1415
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001417 ALOGD("%s: Requested channels are same as current channels(%d)",
1418 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 return 0;
1420 }
1421
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001422 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001424 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425 adev->cur_hdmi_channels = channels;
1426
1427 /*
1428 * Deroute all the playback streams routed to HDMI so that
1429 * the back end is deactivated. Note that backend will not
1430 * be deactivated if any one stream is connected to it.
1431 */
1432 list_for_each(node, &adev->usecase_list) {
1433 usecase = node_to_item(node, struct audio_usecase, list);
1434 if (usecase->type == PCM_PLAYBACK &&
1435 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001436 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001437 }
1438 }
1439
1440 /*
1441 * Enable all the streams disabled above. Now the HDMI backend
1442 * will be activated with new channel configuration
1443 */
1444 list_for_each(node, &adev->usecase_list) {
1445 usecase = node_to_item(node, struct audio_usecase, list);
1446 if (usecase->type == PCM_PLAYBACK &&
1447 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 }
1450 }
1451
1452 return 0;
1453}
1454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455static int stop_output_stream(struct stream_out *out)
1456{
1457 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 struct audio_usecase *uc_info;
1459 struct audio_device *adev = out->dev;
1460
Eric Laurent994a6932013-07-17 11:51:42 -07001461 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 uc_info = get_usecase_from_list(adev, out->usecase);
1464 if (uc_info == NULL) {
1465 ALOGE("%s: Could not find the usecase (%d) in the list",
1466 __func__, out->usecase);
1467 return -EINVAL;
1468 }
1469
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001470 if (is_offload_usecase(out->usecase) &&
1471 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001472 if (adev->visualizer_stop_output != NULL)
1473 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001474
1475 audio_extn_dts_remove_state_notifier_node(out->usecase);
1476
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001477 if (adev->offload_effects_stop_output != NULL)
1478 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1479 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001480
Eric Laurent150dbfe2013-02-27 14:31:02 -08001481 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001482 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483
1484 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001485 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001487 list_remove(&uc_info->list);
1488 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001490 if (is_offload_usecase(out->usecase) &&
1491 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1492 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1493 ALOGV("Disable passthrough , reset mixer to pcm");
1494 /* NO_PASSTHROUGH */
1495 out->compr_config.codec->compr_passthr = 0;
1496 audio_extn_dolby_set_hdmi_config(adev, out);
1497 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1498 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001499 /* Must be called after removing the usecase from list */
1500 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1501 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1502
Eric Laurent994a6932013-07-17 11:51:42 -07001503 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 return ret;
1505}
1506
1507int start_output_stream(struct stream_out *out)
1508{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001510 int sink_channels = 0;
1511 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 struct audio_usecase *uc_info;
1513 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301514 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001516 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1517 ret = -EINVAL;
1518 goto error_config;
1519 }
1520
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301521 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1522 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1523 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301524
Naresh Tanniru80659832014-06-04 18:17:56 +05301525 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301526 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301527 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301528 goto error_config;
1529 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301530
Eric Laurentb23d5282013-05-14 15:27:20 -07001531 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 if (out->pcm_device_id < 0) {
1533 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1534 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001535 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 }
1538
1539 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001540
1541 if (!uc_info) {
1542 ret = -ENOMEM;
1543 goto error_config;
1544 }
1545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 uc_info->id = out->usecase;
1547 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001548 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549 uc_info->devices = out->devices;
1550 uc_info->in_snd_device = SND_DEVICE_NONE;
1551 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001552 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001553 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001554 if (is_offload_usecase(out->usecase)) {
1555 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001556 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1557 }
1558 }
Mingming Yin9c041392014-05-01 15:37:31 -07001559 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1560 if (!strncmp("true", prop_value, 4)) {
1561 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001562 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1563 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001564 check_and_set_hdmi_channels(adev, sink_channels);
1565 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001566 if (is_offload_usecase(out->usecase)) {
1567 unsigned int ch_count = out->compr_config.codec->ch_in;
1568 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1569 /* backend channel config for passthrough stream is stereo */
1570 ch_count = 2;
1571 check_and_set_hdmi_channels(adev, ch_count);
1572 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001573 check_and_set_hdmi_channels(adev, out->config.channels);
1574 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001575 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001576 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001577 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579 select_devices(adev, out->usecase);
1580
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001581 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1582 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001583 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 unsigned int flags = PCM_OUT;
1585 unsigned int pcm_open_retry_count = 0;
1586 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1587 flags |= PCM_MMAP | PCM_NOIRQ;
1588 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1589 } else
1590 flags |= PCM_MONOTONIC;
1591
1592 while (1) {
1593 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1594 flags, &out->config);
1595 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1596 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1597 if (out->pcm != NULL) {
1598 pcm_close(out->pcm);
1599 out->pcm = NULL;
1600 }
1601 if (pcm_open_retry_count-- == 0) {
1602 ret = -EIO;
1603 goto error_open;
1604 }
1605 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1606 continue;
1607 }
1608 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001610 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1611 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001613 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1614 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001616 out->compr = compress_open(adev->snd_card,
1617 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 COMPRESS_IN, &out->compr_config);
1619 if (out->compr && !is_compress_ready(out->compr)) {
1620 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1621 compress_close(out->compr);
1622 out->compr = NULL;
1623 ret = -EIO;
1624 goto error_open;
1625 }
1626 if (out->offload_callback)
1627 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001628
Fred Oh3f43e742015-03-04 18:42:34 -08001629 /* Since small bufs uses blocking writes, a write will be blocked
1630 for the default max poll time (20s) in the event of an SSR.
1631 Reduce the poll time to observe and deal with SSR faster.
1632 */
1633 if (out->use_small_bufs) {
1634 compress_set_max_poll_wait(out->compr, 1000);
1635 }
1636
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001637 audio_extn_dts_create_state_notifier_node(out->usecase);
1638 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1639 popcount(out->channel_mask),
1640 out->playback_started);
1641
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001642#ifdef DS1_DOLBY_DDP_ENABLED
1643 if (audio_extn_is_dolby_format(out->format))
1644 audio_extn_dolby_send_ddp_endp_params(adev);
1645#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001646 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1647 if (adev->visualizer_start_output != NULL)
1648 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1649 if (adev->offload_effects_start_output != NULL)
1650 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001651 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
Eric Laurent994a6932013-07-17 11:51:42 -07001654 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001656error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001658error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001659 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660}
1661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662static int check_input_parameters(uint32_t sample_rate,
1663 audio_format_t format,
1664 int channel_count)
1665{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001666 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001668 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001669 !voice_extn_compress_voip_is_format_supported(format) &&
1670 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001671
1672 switch (channel_count) {
1673 case 1:
1674 case 2:
1675 case 6:
1676 break;
1677 default:
1678 ret = -EINVAL;
1679 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680
1681 switch (sample_rate) {
1682 case 8000:
1683 case 11025:
1684 case 12000:
1685 case 16000:
1686 case 22050:
1687 case 24000:
1688 case 32000:
1689 case 44100:
1690 case 48000:
1691 break;
1692 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001693 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001696 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697}
1698
1699static size_t get_input_buffer_size(uint32_t sample_rate,
1700 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001701 int channel_count,
1702 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703{
1704 size_t size = 0;
1705
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001706 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1707 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001709 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001710 if (is_low_latency)
1711 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001712 /* ToDo: should use frame_size computed based on the format and
1713 channel_count here. */
1714 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001716 /* make sure the size is multiple of 32 bytes
1717 * At 48 kHz mono 16-bit PCM:
1718 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1719 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1720 */
1721 size += 0x1f;
1722 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001723
1724 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725}
1726
1727static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1728{
1729 struct stream_out *out = (struct stream_out *)stream;
1730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732}
1733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001734static int out_set_sample_rate(struct audio_stream *stream __unused,
1735 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736{
1737 return -ENOSYS;
1738}
1739
1740static size_t out_get_buffer_size(const struct audio_stream *stream)
1741{
1742 struct stream_out *out = (struct stream_out *)stream;
1743
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001744 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001746 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1747 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001749 return out->config.period_size *
1750 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751}
1752
1753static uint32_t out_get_channels(const struct audio_stream *stream)
1754{
1755 struct stream_out *out = (struct stream_out *)stream;
1756
1757 return out->channel_mask;
1758}
1759
1760static audio_format_t out_get_format(const struct audio_stream *stream)
1761{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 struct stream_out *out = (struct stream_out *)stream;
1763
1764 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765}
1766
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001767static int out_set_format(struct audio_stream *stream __unused,
1768 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769{
1770 return -ENOSYS;
1771}
1772
1773static int out_standby(struct audio_stream *stream)
1774{
1775 struct stream_out *out = (struct stream_out *)stream;
1776 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301778 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1779 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001780 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1781 /* Ignore standby in case of voip call because the voip output
1782 * stream is closed in adev_close_output_stream()
1783 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301784 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001785 return 0;
1786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001790 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001792 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 if (out->pcm) {
1794 pcm_close(out->pcm);
1795 out->pcm = NULL;
1796 }
1797 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001798 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800 out->gapless_mdata.encoder_delay = 0;
1801 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802 if (out->compr != NULL) {
1803 compress_close(out->compr);
1804 out->compr = NULL;
1805 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001808 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 }
1810 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001811 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 return 0;
1813}
1814
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001815static int out_dump(const struct audio_stream *stream __unused,
1816 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817{
1818 return 0;
1819}
1820
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1822{
1823 int ret = 0;
1824 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301825 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001826
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001828 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 return -EINVAL;
1830 }
1831
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301832 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001833
Yadav Anamikafbcef792015-08-19 16:15:00 +05301834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1835 if(ret >= 0)
1836 is_meta_data_params = true;
1837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1838 if(ret >= 0)
1839 is_meta_data_params = true;
1840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1841 if(ret >= 0)
1842 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1844 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301845 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301846 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001847 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1849 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301850 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301851 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001852 }
1853
Yadav Anamikafbcef792015-08-19 16:15:00 +05301854 if(!is_meta_data_params) {
1855 ALOGV("%s: Not gapless meta data params", __func__);
1856 return 0;
1857 }
1858 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 ALOGV("%s new encoder delay %u and padding %u", __func__,
1860 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1861
1862 return 0;
1863}
1864
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001865static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1866{
1867 return out == adev->primary_output || out == adev->voice_tx_output;
1868}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1871{
1872 struct stream_out *out = (struct stream_out *)stream;
1873 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001874 struct audio_usecase *usecase;
1875 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 struct str_parms *parms;
1877 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001878 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001879 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880
sangwoobc677242013-08-08 16:53:43 +09001881 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301884 if (!parms)
1885 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001886 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1887 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001890 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001892 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301893 * When HDMI cable is unplugged/usb hs is disconnected the
1894 * music playback is paused and the policy manager sends routing=0
1895 * But the audioflingercontinues to write data until standby time
1896 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001897 * Avoid this by routing audio to speaker until standby.
1898 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301899 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1900 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001902 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1903 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 }
1905
1906 /*
1907 * select_devices() call below switches all the usecases on the same
1908 * backend to the new device. Refer to check_usecases_codec_backend() in
1909 * the select_devices(). But how do we undo this?
1910 *
1911 * For example, music playback is active on headset (deep-buffer usecase)
1912 * and if we go to ringtones and select a ringtone, low-latency usecase
1913 * will be started on headset+speaker. As we can't enable headset+speaker
1914 * and headset devices at the same time, select_devices() switches the music
1915 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1916 * So when the ringtone playback is completed, how do we undo the same?
1917 *
1918 * We are relying on the out_set_parameters() call on deep-buffer output,
1919 * once the ringtone playback is ended.
1920 * NOTE: We should not check if the current devices are same as new devices.
1921 * Because select_devices() must be called to switch back the music
1922 * playback to headset.
1923 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001924 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 out->devices = val;
1926
1927 if (!out->standby)
1928 select_devices(adev, out->usecase);
1929
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001930 if (output_drives_call(adev, out)) {
1931 if(!voice_is_in_call(adev)) {
1932 if (adev->mode == AUDIO_MODE_IN_CALL) {
1933 adev->current_call_output = out;
1934 ret = voice_start_call(adev);
1935 }
1936 } else {
1937 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001938 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001939 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001940 }
1941 }
1942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001944 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001946
1947 if (out == adev->primary_output) {
1948 pthread_mutex_lock(&adev->lock);
1949 audio_extn_set_parameters(adev, parms);
1950 pthread_mutex_unlock(&adev->lock);
1951 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001952 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001953 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001954 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001955
1956 audio_extn_dts_create_state_notifier_node(out->usecase);
1957 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1958 popcount(out->channel_mask),
1959 out->playback_started);
1960
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001961 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001962 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301965error:
Eric Laurent994a6932013-07-17 11:51:42 -07001966 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 return ret;
1968}
1969
1970static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1971{
1972 struct stream_out *out = (struct stream_out *)stream;
1973 struct str_parms *query = str_parms_create_str(keys);
1974 char *str;
1975 char value[256];
1976 struct str_parms *reply = str_parms_create();
1977 size_t i, j;
1978 int ret;
1979 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001980
1981 if (!query || !reply) {
1982 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1983 return NULL;
1984 }
1985
Eric Laurent994a6932013-07-17 11:51:42 -07001986 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1988 if (ret >= 0) {
1989 value[0] = '\0';
1990 i = 0;
1991 while (out->supported_channel_masks[i] != 0) {
1992 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1993 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1994 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001995 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001997 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 first = false;
1999 break;
2000 }
2001 }
2002 i++;
2003 }
2004 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2005 str = str_parms_to_str(reply);
2006 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002007 voice_extn_out_get_parameters(out, query, reply);
2008 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002009 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002010 free(str);
2011 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002014
2015 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2016 if (ret >= 0) {
2017 value[0] = '\0';
2018 i = 0;
2019 first = true;
2020 while (out->supported_formats[i] != 0) {
2021 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2022 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2023 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002024 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002025 }
2026 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2027 first = false;
2028 break;
2029 }
2030 }
2031 i++;
2032 }
2033 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2034 str = str_parms_to_str(reply);
2035 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 str_parms_destroy(query);
2037 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002038 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 return str;
2040}
2041
2042static uint32_t out_get_latency(const struct audio_stream_out *stream)
2043{
2044 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002045 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046
Alexy Josephaa54c872014-12-03 02:46:47 -08002047 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002048 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002049 } else {
2050 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002052 }
2053
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302054 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002055 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056}
2057
2058static int out_set_volume(struct audio_stream_out *stream, float left,
2059 float right)
2060{
Eric Laurenta9024de2013-04-04 09:19:12 -07002061 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 int volume[2];
2063
Eric Laurenta9024de2013-04-04 09:19:12 -07002064 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2065 /* only take left channel into account: the API is for stereo anyway */
2066 out->muted = (left == 0.0f);
2067 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002068 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002069 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2070 /*
2071 * Set mute or umute on HDMI passthrough stream.
2072 * Only take left channel into account.
2073 * Mute is 0 and unmute 1
2074 */
2075 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2076 } else {
2077 char mixer_ctl_name[128];
2078 struct audio_device *adev = out->dev;
2079 struct mixer_ctl *ctl;
2080 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002081 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002083 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2084 "Compress Playback %d Volume", pcm_device_id);
2085 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2086 if (!ctl) {
2087 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2088 __func__, mixer_ctl_name);
2089 return -EINVAL;
2090 }
2091 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2092 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2093 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2094 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002096 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 return -ENOSYS;
2099}
2100
2101static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2102 size_t bytes)
2103{
2104 struct stream_out *out = (struct stream_out *)stream;
2105 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302106 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002107 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302110
Naresh Tanniru80659832014-06-04 18:17:56 +05302111 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002112 // increase written size during SSR to avoid mismatch
2113 // with the written frames count in AF
2114 if (!is_offload_usecase(out->usecase))
2115 out->written += bytes / (out->config.channels * sizeof(short));
2116
Naresh Tanniru80659832014-06-04 18:17:56 +05302117 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302118 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302119 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302120 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002121 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302122 //during SSR for compress usecase we should return error to flinger
2123 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2124 pthread_mutex_unlock(&out->lock);
2125 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302126 }
2127 }
2128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002130 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002131 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002132 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2133 ret = voice_extn_compress_voip_start_output_stream(out);
2134 else
2135 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002136 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002139 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 goto exit;
2141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302144 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2145 setChannelStatus(out, buffer, bytes);
2146 adev->mChannelStatusSet = true;
2147 }
2148
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002149 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002150 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002151 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002152 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002153 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2154 out->send_new_metadata = 0;
2155 }
2156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302158 if (ret < 0)
2159 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002161 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302162 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302164 } else if (-ENETRESET == ret) {
2165 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2166 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2167 pthread_mutex_unlock(&out->lock);
2168 out_standby(&out->stream.common);
2169 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002170 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302171 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002173 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 out->playback_started = 1;
2175 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002176
2177 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2178 popcount(out->channel_mask),
2179 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 }
2181 pthread_mutex_unlock(&out->lock);
2182 return ret;
2183 } else {
2184 if (out->pcm) {
2185 if (out->muted)
2186 memset((void *)buffer, 0, bytes);
2187 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002188 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2189 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2190 else
2191 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302192 if (ret < 0)
2193 ret = -errno;
2194 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002195 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 }
2198
2199exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302200 /* ToDo: There may be a corner case when SSR happens back to back during
2201 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302202 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302204 }
2205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206 pthread_mutex_unlock(&out->lock);
2207
2208 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002209 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002210 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302211 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302212 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302213 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302214 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302215 out->standby = true;
2216 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002218 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302219 out_get_sample_rate(&out->stream.common));
2220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 }
2222 return bytes;
2223}
2224
2225static int out_get_render_position(const struct audio_stream_out *stream,
2226 uint32_t *dsp_frames)
2227{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302229 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002230
2231 if (dsp_frames == NULL)
2232 return -EINVAL;
2233
2234 *dsp_frames = 0;
2235 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002236 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 pthread_mutex_lock(&out->lock);
2238 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302239 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302241 if (ret < 0)
2242 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 ALOGVV("%s rendered frames %d sample_rate %d",
2244 __func__, *dsp_frames, out->sample_rate);
2245 }
2246 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302247 if (-ENETRESET == ret) {
2248 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2249 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2250 return -EINVAL;
2251 } else if(ret < 0) {
2252 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2253 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302254 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2255 /*
2256 * Handle corner case where compress session is closed during SSR
2257 * and timestamp is queried
2258 */
2259 ALOGE(" ERROR: sound card not active, return error");
2260 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302261 } else {
2262 return 0;
2263 }
Zhou Song32a556e2015-05-05 10:46:56 +08002264 } else if (audio_is_linear_pcm(out->format)) {
2265 *dsp_frames = out->written;
2266 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 } else
2268 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269}
2270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002271static int out_add_audio_effect(const struct audio_stream *stream __unused,
2272 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273{
2274 return 0;
2275}
2276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002277static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2278 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279{
2280 return 0;
2281}
2282
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002283static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2284 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285{
2286 return -EINVAL;
2287}
2288
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002289static int out_get_presentation_position(const struct audio_stream_out *stream,
2290 uint64_t *frames, struct timespec *timestamp)
2291{
2292 struct stream_out *out = (struct stream_out *)stream;
2293 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002294 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002295
2296 pthread_mutex_lock(&out->lock);
2297
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002298 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002299 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302300 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002301 &out->sample_rate);
2302 ALOGVV("%s rendered frames %ld sample_rate %d",
2303 __func__, dsp_frames, out->sample_rate);
2304 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302305 if (ret < 0)
2306 ret = -errno;
2307 if (-ENETRESET == ret) {
2308 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2309 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2310 ret = -EINVAL;
2311 } else
2312 ret = 0;
2313
Eric Laurent949a0892013-09-20 09:20:13 -07002314 /* this is the best we can do */
2315 clock_gettime(CLOCK_MONOTONIC, timestamp);
2316 }
2317 } else {
2318 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002319 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002320 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2321 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002322 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002323 // This adjustment accounts for buffering after app processor.
2324 // It is based on estimated DSP latency per use case, rather than exact.
2325 signed_frames -=
2326 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2327
Eric Laurent949a0892013-09-20 09:20:13 -07002328 // It would be unusual for this value to be negative, but check just in case ...
2329 if (signed_frames >= 0) {
2330 *frames = signed_frames;
2331 ret = 0;
2332 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002333 }
2334 }
2335 }
2336
2337 pthread_mutex_unlock(&out->lock);
2338
2339 return ret;
2340}
2341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342static int out_set_callback(struct audio_stream_out *stream,
2343 stream_callback_t callback, void *cookie)
2344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346
2347 ALOGV("%s", __func__);
2348 pthread_mutex_lock(&out->lock);
2349 out->offload_callback = callback;
2350 out->offload_cookie = cookie;
2351 pthread_mutex_unlock(&out->lock);
2352 return 0;
2353}
2354
2355static int out_pause(struct audio_stream_out* stream)
2356{
2357 struct stream_out *out = (struct stream_out *)stream;
2358 int status = -ENOSYS;
2359 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002360 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002361 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 pthread_mutex_lock(&out->lock);
2363 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302364 struct audio_device *adev = out->dev;
2365 int snd_scard_state = get_snd_card_state(adev);
2366
2367 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2368 status = compress_pause(out->compr);
2369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002371
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302372 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002373 audio_extn_dts_notify_playback_state(out->usecase, 0,
2374 out->sample_rate, popcount(out->channel_mask),
2375 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 }
2377 pthread_mutex_unlock(&out->lock);
2378 }
2379 return status;
2380}
2381
2382static int out_resume(struct audio_stream_out* stream)
2383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385 int status = -ENOSYS;
2386 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002387 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002388 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 status = 0;
2390 pthread_mutex_lock(&out->lock);
2391 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302392 struct audio_device *adev = out->dev;
2393 int snd_scard_state = get_snd_card_state(adev);
2394
2395 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2396 status = compress_resume(out->compr);
2397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302400 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002401 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2402 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 }
2404 pthread_mutex_unlock(&out->lock);
2405 }
2406 return status;
2407}
2408
2409static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2410{
2411 struct stream_out *out = (struct stream_out *)stream;
2412 int status = -ENOSYS;
2413 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002414 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 pthread_mutex_lock(&out->lock);
2416 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2417 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2418 else
2419 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2420 pthread_mutex_unlock(&out->lock);
2421 }
2422 return status;
2423}
2424
2425static int out_flush(struct audio_stream_out* stream)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002430 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002431 pthread_mutex_lock(&out->lock);
2432 stop_compressed_output_l(out);
2433 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002434 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002435 return 0;
2436 }
2437 return -ENOSYS;
2438}
2439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440/** audio_stream_in implementation **/
2441static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2442{
2443 struct stream_in *in = (struct stream_in *)stream;
2444
2445 return in->config.rate;
2446}
2447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002448static int in_set_sample_rate(struct audio_stream *stream __unused,
2449 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450{
2451 return -ENOSYS;
2452}
2453
2454static size_t in_get_buffer_size(const struct audio_stream *stream)
2455{
2456 struct stream_in *in = (struct stream_in *)stream;
2457
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002458 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2459 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002460 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2461 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002462
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002463 return in->config.period_size *
2464 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465}
2466
2467static uint32_t in_get_channels(const struct audio_stream *stream)
2468{
2469 struct stream_in *in = (struct stream_in *)stream;
2470
2471 return in->channel_mask;
2472}
2473
2474static audio_format_t in_get_format(const struct audio_stream *stream)
2475{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002476 struct stream_in *in = (struct stream_in *)stream;
2477
2478 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479}
2480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002481static int in_set_format(struct audio_stream *stream __unused,
2482 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483{
2484 return -ENOSYS;
2485}
2486
2487static int in_standby(struct audio_stream *stream)
2488{
2489 struct stream_in *in = (struct stream_in *)stream;
2490 struct audio_device *adev = in->dev;
2491 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302492 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2493 stream, in->usecase, use_case_table[in->usecase]);
2494
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002495 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2496 /* Ignore standby in case of voip call because the voip input
2497 * stream is closed in adev_close_input_stream()
2498 */
2499 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2500 return status;
2501 }
2502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002504 if (!in->standby && in->is_st_session) {
2505 ALOGD("%s: sound trigger pcm stop lab", __func__);
2506 audio_extn_sound_trigger_stop_lab(in);
2507 in->standby = 1;
2508 }
2509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002511 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002513 if (in->pcm) {
2514 pcm_close(in->pcm);
2515 in->pcm = NULL;
2516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002518 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 }
2520 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002521 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 return status;
2523}
2524
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002525static int in_dump(const struct audio_stream *stream __unused,
2526 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527{
2528 return 0;
2529}
2530
2531static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2532{
2533 struct stream_in *in = (struct stream_in *)stream;
2534 struct audio_device *adev = in->dev;
2535 struct str_parms *parms;
2536 char *str;
2537 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002538 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302540 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 parms = str_parms_create_str(kvpairs);
2542
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302543 if (!parms)
2544 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002546 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002547
2548 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2549 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 val = atoi(value);
2551 /* no audio source uses val == 0 */
2552 if ((in->source != val) && (val != 0)) {
2553 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002554 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2555 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2556 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2557 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002558 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002559 err = voice_extn_compress_voip_open_input_stream(in);
2560 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002561 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002562 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002563 }
2564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 }
2566 }
2567
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002568 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2569 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002571 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 in->device = val;
2573 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002574 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002575 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 }
2577 }
2578
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002579done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
2583 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302584error:
Eric Laurent994a6932013-07-17 11:51:42 -07002585 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 return ret;
2587}
2588
2589static char* in_get_parameters(const struct audio_stream *stream,
2590 const char *keys)
2591{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002592 struct stream_in *in = (struct stream_in *)stream;
2593 struct str_parms *query = str_parms_create_str(keys);
2594 char *str;
2595 char value[256];
2596 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002597
2598 if (!query || !reply) {
2599 ALOGE("in_get_parameters: failed to create query or reply");
2600 return NULL;
2601 }
2602
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002603 ALOGV("%s: enter: keys - %s", __func__, keys);
2604
2605 voice_extn_in_get_parameters(in, query, reply);
2606
2607 str = str_parms_to_str(reply);
2608 str_parms_destroy(query);
2609 str_parms_destroy(reply);
2610
2611 ALOGV("%s: exit: returns - %s", __func__, str);
2612 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613}
2614
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002615static int in_set_gain(struct audio_stream_in *stream __unused,
2616 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617{
2618 return 0;
2619}
2620
2621static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2622 size_t bytes)
2623{
2624 struct stream_in *in = (struct stream_in *)stream;
2625 struct audio_device *adev = in->dev;
2626 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302627 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302630
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002631 if (in->is_st_session) {
2632 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2633 /* Read from sound trigger HAL */
2634 audio_extn_sound_trigger_read(in, buffer, bytes);
2635 pthread_mutex_unlock(&in->lock);
2636 return bytes;
2637 }
2638
2639 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2640 ALOGD(" %s: sound card is not active/SSR state", __func__);
2641 ret= -EIO;;
2642 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302643 }
2644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002646 pthread_mutex_lock(&adev->lock);
2647 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2648 ret = voice_extn_compress_voip_start_input_stream(in);
2649 else
2650 ret = start_input_stream(in);
2651 pthread_mutex_unlock(&adev->lock);
2652 if (ret != 0) {
2653 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 }
2655 in->standby = 0;
2656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
2658 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002659 if (audio_extn_ssr_get_enabled() &&
2660 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002661 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002662 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2663 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002664 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2665 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002666 else
2667 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302668 if (ret < 0)
2669 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 }
2671
2672 /*
2673 * Instead of writing zeroes here, we could trust the hardware
2674 * to always provide zeroes when muted.
2675 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302676 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2677 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 memset(buffer, 0, bytes);
2679
2680exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302681 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302682 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002683 if (-ENETRESET == ret)
2684 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 pthread_mutex_unlock(&in->lock);
2687
2688 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302689 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302690 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302691 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302692 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302693 in->standby = true;
2694 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302695 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002697 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002698 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302699 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 }
2701 return bytes;
2702}
2703
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002704static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705{
2706 return 0;
2707}
2708
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002709static int add_remove_audio_effect(const struct audio_stream *stream,
2710 effect_handle_t effect,
2711 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713 struct stream_in *in = (struct stream_in *)stream;
2714 int status = 0;
2715 effect_descriptor_t desc;
2716
2717 status = (*effect)->get_descriptor(effect, &desc);
2718 if (status != 0)
2719 return status;
2720
2721 pthread_mutex_lock(&in->lock);
2722 pthread_mutex_lock(&in->dev->lock);
2723 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2724 in->enable_aec != enable &&
2725 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2726 in->enable_aec = enable;
2727 if (!in->standby)
2728 select_devices(in->dev, in->usecase);
2729 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002730 if (in->enable_ns != enable &&
2731 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2732 in->enable_ns = enable;
2733 if (!in->standby)
2734 select_devices(in->dev, in->usecase);
2735 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002736 pthread_mutex_unlock(&in->dev->lock);
2737 pthread_mutex_unlock(&in->lock);
2738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 return 0;
2740}
2741
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002742static int in_add_audio_effect(const struct audio_stream *stream,
2743 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744{
Eric Laurent994a6932013-07-17 11:51:42 -07002745 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002746 return add_remove_audio_effect(stream, effect, true);
2747}
2748
2749static int in_remove_audio_effect(const struct audio_stream *stream,
2750 effect_handle_t effect)
2751{
Eric Laurent994a6932013-07-17 11:51:42 -07002752 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002753 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754}
2755
2756static int adev_open_output_stream(struct audio_hw_device *dev,
2757 audio_io_handle_t handle,
2758 audio_devices_t devices,
2759 audio_output_flags_t flags,
2760 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002761 struct audio_stream_out **stream_out,
2762 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763{
2764 struct audio_device *adev = (struct audio_device *)dev;
2765 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002766 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002767 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302770
2771 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2772 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2773 ALOGE(" sound card is not active rejecting compress output open request");
2774 return -EINVAL;
2775 }
2776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2778
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302779 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2780 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2781 devices, flags, &out->stream);
2782
2783
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002784 if (!out) {
2785 return -ENOMEM;
2786 }
2787
Haynes Mathew George204045b2015-02-25 20:32:03 -08002788 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2789 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 if (devices == AUDIO_DEVICE_NONE)
2792 devices = AUDIO_DEVICE_OUT_SPEAKER;
2793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 out->flags = flags;
2795 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002796 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002797 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 out->sample_rate = config->sample_rate;
2799 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2800 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002801 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002802 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002803 out->non_blocking = 0;
2804 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302806 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2807 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002808 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2809 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2810
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002811 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002812 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2813 ret = read_hdmi_channel_masks(out);
2814
2815 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2816 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002817 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002818 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002819 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002820
2821 if (config->sample_rate == 0)
2822 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2823 if (config->channel_mask == 0)
2824 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2825
2826 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2829 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002831 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002833 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2834 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002835 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002836 ret = voice_extn_compress_voip_open_output_stream(out);
2837 if (ret != 0) {
2838 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2839 __func__, ret);
2840 goto error_open;
2841 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2843 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2844 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2845 ALOGE("%s: Unsupported Offload information", __func__);
2846 ret = -EINVAL;
2847 goto error_open;
2848 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002849
2850 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2851 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2852 ALOGV("read and update_pass through formats");
2853 ret = audio_extn_dolby_update_passt_formats(adev, out);
2854 if(ret != 0) {
2855 goto error_open;
2856 }
2857 if(config->offload_info.format == 0)
2858 config->offload_info.format = out->supported_formats[0];
2859 }
2860
Mingming Yin90310102013-11-13 16:57:00 -08002861 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002862 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 ALOGE("%s: Unsupported audio format", __func__);
2864 ret = -EINVAL;
2865 goto error_open;
2866 }
2867
2868 out->compr_config.codec = (struct snd_codec *)
2869 calloc(1, sizeof(struct snd_codec));
2870
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002871 if (!out->compr_config.codec) {
2872 ret = -ENOMEM;
2873 goto error_open;
2874 }
2875
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002876 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 if (config->offload_info.channel_mask)
2878 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002879 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002881 config->offload_info.channel_mask = config->channel_mask;
2882 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002883 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 out->sample_rate = config->offload_info.sample_rate;
2885
2886 out->stream.set_callback = out_set_callback;
2887 out->stream.pause = out_pause;
2888 out->stream.resume = out_resume;
2889 out->stream.drain = out_drain;
2890 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002891 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002893 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002894 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002895 audio_extn_dolby_get_snd_codec_id(adev, out,
2896 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002897 else
2898 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302900 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002901 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902 platform_get_pcm_offload_buffer_size(&config->offload_info);
2903 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2904 out->compr_config.fragment_size =
2905 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 } else {
2907 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002908 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002909 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2911 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002912 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 out->compr_config.codec->bit_rate =
2914 config->offload_info.bit_rate;
2915 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002916 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302918 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002919 /*TODO: Do we need to change it for passthrough */
2920 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921
Manish Dewangan93672f12015-08-24 20:30:31 +05302922 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2923 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2924 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2925 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002926 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2927 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002928 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2930
Mingming Yin3ee55c62014-08-04 14:23:35 -07002931 if (out->bit_width == 24) {
2932 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2933 }
2934
Amit Shekhar6f461b12014-08-01 14:52:58 -07002935 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302936 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2939 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002940
Sharad Sangleb27354b2015-06-18 15:58:55 +05302941 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002942 //this flag is set from framework only if its for PCM formats
2943 //no need to check for PCM format again
2944 out->non_blocking = 0;
2945 out->use_small_bufs = true;
2946 ALOGI("Keep write blocking for small buff: non_blockling %d",
2947 out->non_blocking);
2948 }
2949
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002950 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002951 out->offload_state = OFFLOAD_STATE_IDLE;
2952 out->playback_started = 0;
2953
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002954 audio_extn_dts_create_state_notifier_node(out->usecase);
2955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 create_offload_callback_thread(out);
2957 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2958 __func__, config->offload_info.version,
2959 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002960 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002961 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002962 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2963 ret = voice_check_and_set_incall_music_usecase(adev, out);
2964 if (ret != 0) {
2965 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2966 __func__, ret);
2967 goto error_open;
2968 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002969 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2970 if (config->sample_rate == 0)
2971 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2972 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2973 config->sample_rate != 8000) {
2974 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2975 ret = -EINVAL;
2976 goto error_open;
2977 }
2978 out->sample_rate = config->sample_rate;
2979 out->config.rate = config->sample_rate;
2980 if (config->format == AUDIO_FORMAT_DEFAULT)
2981 config->format = AUDIO_FORMAT_PCM_16_BIT;
2982 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2983 config->format = AUDIO_FORMAT_PCM_16_BIT;
2984 ret = -EINVAL;
2985 goto error_open;
2986 }
2987 out->format = config->format;
2988 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2989 out->config = pcm_config_afe_proxy_playback;
2990 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002991 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002992 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2994 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002995 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002996 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2997 format = AUDIO_FORMAT_PCM_16_BIT;
2998 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2999 out->config = pcm_config_deep_buffer;
3000 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003001 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003002 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003003 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003004 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003005 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003006 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 }
3008
Amit Shekhar1d896042014-10-03 13:16:09 -07003009 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3010 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003011 /* TODO remove this hardcoding and check why width is zero*/
3012 if (out->bit_width == 0)
3013 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003014 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3015 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003016 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303017 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003018 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3019 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3020 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003021 if(adev->primary_output == NULL)
3022 adev->primary_output = out;
3023 else {
3024 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003025 ret = -EEXIST;
3026 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003027 }
3028 }
3029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 /* Check if this usecase is already existing */
3031 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003032 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3033 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003036 ret = -EEXIST;
3037 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 }
3039 pthread_mutex_unlock(&adev->lock);
3040
3041 out->stream.common.get_sample_rate = out_get_sample_rate;
3042 out->stream.common.set_sample_rate = out_set_sample_rate;
3043 out->stream.common.get_buffer_size = out_get_buffer_size;
3044 out->stream.common.get_channels = out_get_channels;
3045 out->stream.common.get_format = out_get_format;
3046 out->stream.common.set_format = out_set_format;
3047 out->stream.common.standby = out_standby;
3048 out->stream.common.dump = out_dump;
3049 out->stream.common.set_parameters = out_set_parameters;
3050 out->stream.common.get_parameters = out_get_parameters;
3051 out->stream.common.add_audio_effect = out_add_audio_effect;
3052 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3053 out->stream.get_latency = out_get_latency;
3054 out->stream.set_volume = out_set_volume;
3055 out->stream.write = out_write;
3056 out->stream.get_render_position = out_get_render_position;
3057 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003058 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003061 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003062 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063
3064 config->format = out->stream.common.get_format(&out->stream.common);
3065 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3066 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3067
3068 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303069 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3070 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003071
3072 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3073 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3074 popcount(out->channel_mask), out->playback_started);
3075
Eric Laurent994a6932013-07-17 11:51:42 -07003076 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003078
3079error_open:
3080 free(out);
3081 *stream_out = NULL;
3082 ALOGD("%s: exit: ret %d", __func__, ret);
3083 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003086static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 struct audio_stream_out *stream)
3088{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 struct stream_out *out = (struct stream_out *)stream;
3090 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003091 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303093 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3094
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303096 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003097 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303098 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003099 if(ret != 0)
3100 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3101 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003102 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003103 out_standby(&stream->common);
3104
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003105 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003106 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003108 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 if (out->compr_config.codec != NULL)
3110 free(out->compr_config.codec);
3111 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112
3113 if (adev->voice_tx_output == out)
3114 adev->voice_tx_output = NULL;
3115
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 pthread_cond_destroy(&out->cond);
3117 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003119 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120}
3121
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003122static void close_compress_sessions(struct audio_device *adev)
3123{
Mingming Yin7b762e72015-03-04 13:47:32 -08003124 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303125 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003126 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003127 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303128
3129 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303131 if (is_offload_usecase(usecase->id)) {
3132 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003133 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3134 out = usecase->stream.out;
3135 pthread_mutex_unlock(&adev->lock);
3136 out_standby(&out->stream.common);
3137 pthread_mutex_lock(&adev->lock);
3138 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303139 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003140 }
3141 pthread_mutex_unlock(&adev->lock);
3142}
3143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3145{
3146 struct audio_device *adev = (struct audio_device *)dev;
3147 struct str_parms *parms;
3148 char *str;
3149 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003150 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003151 int ret;
3152 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003154 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303157 if (!parms)
3158 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3160 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303163 struct listnode *node;
3164 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303165 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303166 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003167 //close compress sessions on OFFLINE status
3168 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303169 } else if (strstr(snd_card_status, "ONLINE")) {
3170 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303171 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303172 if (!platform_is_acdb_initialized(adev->platform)) {
3173 ret = platform_acdb_init(adev->platform);
3174 if(ret)
3175 ALOGE("acdb initialization is failed");
3176
3177 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303178 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303179 }
3180
3181 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 status = voice_set_parameters(adev, parms);
3183 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003184 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003186 status = platform_set_parameters(adev->platform, parms);
3187 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003188 goto done;
3189
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003190 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3191 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003192 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3194 adev->bluetooth_nrec = true;
3195 else
3196 adev->bluetooth_nrec = false;
3197 }
3198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003199 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3200 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3202 adev->screen_off = false;
3203 else
3204 adev->screen_off = true;
3205 }
3206
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003207 ret = str_parms_get_int(parms, "rotation", &val);
3208 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003209 bool reverse_speakers = false;
3210 switch(val) {
3211 // FIXME: note that the code below assumes that the speakers are in the correct placement
3212 // relative to the user when the device is rotated 90deg from its default rotation. This
3213 // assumption is device-specific, not platform-specific like this code.
3214 case 270:
3215 reverse_speakers = true;
3216 break;
3217 case 0:
3218 case 90:
3219 case 180:
3220 break;
3221 default:
3222 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003223 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003224 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003225 if (status == 0) {
3226 if (adev->speaker_lr_swap != reverse_speakers) {
3227 adev->speaker_lr_swap = reverse_speakers;
3228 // only update the selected device if there is active pcm playback
3229 struct audio_usecase *usecase;
3230 struct listnode *node;
3231 list_for_each(node, &adev->usecase_list) {
3232 usecase = node_to_item(node, struct audio_usecase, list);
3233 if (usecase->type == PCM_PLAYBACK) {
3234 select_devices(adev, usecase->id);
3235 break;
3236 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003237 }
3238 }
3239 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003240 }
3241
Mingming Yin514a8bc2014-07-29 15:22:21 -07003242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3243 if (ret >= 0) {
3244 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3245 adev->bt_wb_speech_enabled = true;
3246 else
3247 adev->bt_wb_speech_enabled = false;
3248 }
3249
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003250 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3251 if (ret >= 0) {
3252 val = atoi(value);
3253 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3254 ALOGV("cache new edid");
3255 platform_cache_edid(adev->platform);
3256 }
3257 }
3258
3259 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3260 if (ret >= 0) {
3261 val = atoi(value);
3262 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3263 ALOGV("invalidate cached edid");
3264 platform_invalidate_edid(adev->platform);
3265 }
3266 }
3267
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003268 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003269
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003270done:
3271 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003272 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303273error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003274 ALOGV("%s: exit with code(%d)", __func__, status);
3275 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276}
3277
3278static char* adev_get_parameters(const struct audio_hw_device *dev,
3279 const char *keys)
3280{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003281 struct audio_device *adev = (struct audio_device *)dev;
3282 struct str_parms *reply = str_parms_create();
3283 struct str_parms *query = str_parms_create_str(keys);
3284 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303285 char value[256] = {0};
3286 int ret = 0;
3287
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003288 if (!query || !reply) {
3289 ALOGE("adev_get_parameters: failed to create query or reply");
3290 return NULL;
3291 }
3292
Naresh Tannirud7205b62014-06-20 02:54:48 +05303293 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3294 sizeof(value));
3295 if (ret >=0) {
3296 int val = 1;
3297 pthread_mutex_lock(&adev->snd_card_status.lock);
3298 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3299 val = 0;
3300 pthread_mutex_unlock(&adev->snd_card_status.lock);
3301 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3302 goto exit;
3303 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003304
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003305 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003306 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003307 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003308 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303309 pthread_mutex_unlock(&adev->lock);
3310
Naresh Tannirud7205b62014-06-20 02:54:48 +05303311exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003312 str = str_parms_to_str(reply);
3313 str_parms_destroy(query);
3314 str_parms_destroy(reply);
3315
3316 ALOGV("%s: exit: returns - %s", __func__, str);
3317 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
3322 return 0;
3323}
3324
3325static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3326{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003327 int ret;
3328 struct audio_device *adev = (struct audio_device *)dev;
3329 pthread_mutex_lock(&adev->lock);
3330 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003331 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003332 pthread_mutex_unlock(&adev->lock);
3333 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3337 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338{
3339 return -ENOSYS;
3340}
3341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003342static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3343 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344{
3345 return -ENOSYS;
3346}
3347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003348static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3349 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350{
3351 return -ENOSYS;
3352}
3353
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003354static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3355 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356{
3357 return -ENOSYS;
3358}
3359
3360static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3361{
3362 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 pthread_mutex_lock(&adev->lock);
3365 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003366 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003368 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3369 voice_is_in_call(adev)) {
3370 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303371 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003372 adev->current_call_output = NULL;
3373 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 }
3375 pthread_mutex_unlock(&adev->lock);
3376 return 0;
3377}
3378
3379static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3380{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003381 int ret;
3382
3383 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003384 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003385 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3386 pthread_mutex_unlock(&adev->lock);
3387
3388 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389}
3390
3391static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3392{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003393 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 return 0;
3395}
3396
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003397static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 const struct audio_config *config)
3399{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003400 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003402 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3403 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404}
3405
3406static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003407 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 audio_devices_t devices,
3409 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003410 struct audio_stream_in **stream_in,
3411 audio_input_flags_t flags __unused,
3412 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003413 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414{
3415 struct audio_device *adev = (struct audio_device *)dev;
3416 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003417 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003418 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003419 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 *stream_in = NULL;
3422 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3423 return -EINVAL;
3424
3425 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003426
3427 if (!in) {
3428 ALOGE("failed to allocate input stream");
3429 return -ENOMEM;
3430 }
3431
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303432 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003433 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3434 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003436 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in->stream.common.get_sample_rate = in_get_sample_rate;
3439 in->stream.common.set_sample_rate = in_set_sample_rate;
3440 in->stream.common.get_buffer_size = in_get_buffer_size;
3441 in->stream.common.get_channels = in_get_channels;
3442 in->stream.common.get_format = in_get_format;
3443 in->stream.common.set_format = in_set_format;
3444 in->stream.common.standby = in_standby;
3445 in->stream.common.dump = in_dump;
3446 in->stream.common.set_parameters = in_set_parameters;
3447 in->stream.common.get_parameters = in_get_parameters;
3448 in->stream.common.add_audio_effect = in_add_audio_effect;
3449 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3450 in->stream.set_gain = in_set_gain;
3451 in->stream.read = in_read;
3452 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3453
3454 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003455 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 in->standby = 1;
3458 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003459 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
3461 /* Update config params with the requested sample rate and channels */
3462 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003463 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3464 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3465 is_low_latency = true;
3466#if LOW_LATENCY_CAPTURE_USE_CASE
3467 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3468#endif
3469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003472 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003474 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303475 if (adev->mode != AUDIO_MODE_IN_CALL) {
3476 ret = -EINVAL;
3477 goto err_open;
3478 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003479 if (config->sample_rate == 0)
3480 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3481 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3482 config->sample_rate != 8000) {
3483 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3484 ret = -EINVAL;
3485 goto err_open;
3486 }
3487 if (config->format == AUDIO_FORMAT_DEFAULT)
3488 config->format = AUDIO_FORMAT_PCM_16_BIT;
3489 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3490 config->format = AUDIO_FORMAT_PCM_16_BIT;
3491 ret = -EINVAL;
3492 goto err_open;
3493 }
3494
3495 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3496 in->config = pcm_config_afe_proxy_record;
3497 in->config.channels = channel_count;
3498 in->config.rate = config->sample_rate;
3499 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003500 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003501 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003502 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3503 ret = -EINVAL;
3504 goto err_open;
3505 }
3506 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003507 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003508 }
Mingming Yine62d7842013-10-25 16:26:03 -07003509 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003510 audio_extn_compr_cap_format_supported(config->format) &&
3511 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003512 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003513 } else {
3514 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003515 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003516 buffer_size = get_input_buffer_size(config->sample_rate,
3517 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003518 channel_count,
3519 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003521 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3522 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3523 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3524 (in->config.rate == 8000 || in->config.rate == 16000) &&
3525 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3526 voice_extn_compress_voip_open_input_stream(in);
3527 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003530 /* This stream could be for sound trigger lab,
3531 get sound trigger pcm if present */
3532 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303533 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003536 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003537 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
3539err_open:
3540 free(in);
3541 *stream_in = NULL;
3542 return ret;
3543}
3544
3545static void adev_close_input_stream(struct audio_hw_device *dev,
3546 struct audio_stream_in *stream)
3547{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003548 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003549 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003550 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303551
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303552 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003553
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303554 /* Disable echo reference while closing input stream */
3555 platform_set_echo_reference(adev->platform, false);
3556
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003557 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303558 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003559 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303560 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003561 if (ret != 0)
3562 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3563 __func__, ret);
3564 } else
3565 in_standby(&stream->common);
3566
Mingming Yin7b762e72015-03-04 13:47:32 -08003567 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003568 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003569 audio_extn_ssr_deinit();
3570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
Mingming Yine62d7842013-10-25 16:26:03 -07003572 if(audio_extn_compr_cap_enabled() &&
3573 audio_extn_compr_cap_format_supported(in->config.format))
3574 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003575
3576 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 return;
3578}
3579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003580static int adev_dump(const audio_hw_device_t *device __unused,
3581 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582{
3583 return 0;
3584}
3585
3586static int adev_close(hw_device_t *device)
3587{
3588 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003589
3590 if (!adev)
3591 return 0;
3592
3593 pthread_mutex_lock(&adev_init_lock);
3594
3595 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003596 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003597 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003598 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003599 audio_route_free(adev->audio_route);
3600 free(adev->snd_dev_ref_cnt);
3601 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003602 free(device);
3603 adev = NULL;
3604 }
3605 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 return 0;
3607}
3608
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003609/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3610 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3611 * just that it _might_ work.
3612 */
3613static int period_size_is_plausible_for_low_latency(int period_size)
3614{
3615 switch (period_size) {
3616 case 160:
3617 case 240:
3618 case 320:
3619 case 480:
3620 return 1;
3621 default:
3622 return 0;
3623 }
3624}
3625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626static int adev_open(const hw_module_t *module, const char *name,
3627 hw_device_t **device)
3628{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003629 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003631 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3633
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003634 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003635 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003636 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003637 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003638 ALOGD("%s: returning existing instance of adev", __func__);
3639 ALOGD("%s: exit", __func__);
3640 pthread_mutex_unlock(&adev_init_lock);
3641 return 0;
3642 }
3643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 adev = calloc(1, sizeof(struct audio_device));
3645
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003646 if (!adev) {
3647 pthread_mutex_unlock(&adev_init_lock);
3648 return -ENOMEM;
3649 }
3650
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003651 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3654 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3655 adev->device.common.module = (struct hw_module_t *)module;
3656 adev->device.common.close = adev_close;
3657
3658 adev->device.init_check = adev_init_check;
3659 adev->device.set_voice_volume = adev_set_voice_volume;
3660 adev->device.set_master_volume = adev_set_master_volume;
3661 adev->device.get_master_volume = adev_get_master_volume;
3662 adev->device.set_master_mute = adev_set_master_mute;
3663 adev->device.get_master_mute = adev_get_master_mute;
3664 adev->device.set_mode = adev_set_mode;
3665 adev->device.set_mic_mute = adev_set_mic_mute;
3666 adev->device.get_mic_mute = adev_get_mic_mute;
3667 adev->device.set_parameters = adev_set_parameters;
3668 adev->device.get_parameters = adev_get_parameters;
3669 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3670 adev->device.open_output_stream = adev_open_output_stream;
3671 adev->device.close_output_stream = adev_close_output_stream;
3672 adev->device.open_input_stream = adev_open_input_stream;
3673 adev->device.close_input_stream = adev_close_input_stream;
3674 adev->device.dump = adev_dump;
3675
3676 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003678 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003679 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003682 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003683 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003684 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003685 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003686 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003687 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003688 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303689 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303690
3691 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3692 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003694 adev->platform = platform_init(adev);
3695 if (!adev->platform) {
3696 free(adev->snd_dev_ref_cnt);
3697 free(adev);
3698 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3699 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003700 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003701 return -EINVAL;
3702 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003703
Naresh Tanniru4c630392014-05-12 01:05:52 +05303704 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3705
Eric Laurentc4aef752013-09-12 17:45:53 -07003706 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3707 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3708 if (adev->visualizer_lib == NULL) {
3709 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3710 } else {
3711 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3712 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003713 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003714 "visualizer_hal_start_output");
3715 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003716 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003717 "visualizer_hal_stop_output");
3718 }
3719 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003720 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003721 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003722
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003723 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3724 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3725 if (adev->offload_effects_lib == NULL) {
3726 ALOGE("%s: DLOPEN failed for %s", __func__,
3727 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3728 } else {
3729 ALOGV("%s: DLOPEN successful for %s", __func__,
3730 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3731 adev->offload_effects_start_output =
3732 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3733 "offload_effects_bundle_hal_start_output");
3734 adev->offload_effects_stop_output =
3735 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3736 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003737 adev->offload_effects_set_hpx_state =
3738 (int (*)(bool))dlsym(adev->offload_effects_lib,
3739 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303740 adev->offload_effects_get_parameters =
3741 (void (*)(struct str_parms *, struct str_parms *))
3742 dlsym(adev->offload_effects_lib,
3743 "offload_effects_bundle_get_parameters");
3744 adev->offload_effects_set_parameters =
3745 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3746 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003747 }
3748 }
3749
Mingming Yin514a8bc2014-07-29 15:22:21 -07003750 adev->bt_wb_speech_enabled = false;
3751
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003752 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 *device = &adev->device.common;
3754
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003755 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3756 &adev->streams_output_cfg_list);
3757
Kiran Kandi910e1862013-10-29 13:29:42 -07003758 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003759
3760 char value[PROPERTY_VALUE_MAX];
3761 int trial;
3762 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3763 trial = atoi(value);
3764 if (period_size_is_plausible_for_low_latency(trial)) {
3765 pcm_config_low_latency.period_size = trial;
3766 pcm_config_low_latency.start_threshold = trial / 4;
3767 pcm_config_low_latency.avail_min = trial / 4;
3768 configured_low_latency_capture_period_size = trial;
3769 }
3770 }
3771 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3772 trial = atoi(value);
3773 if (period_size_is_plausible_for_low_latency(trial)) {
3774 configured_low_latency_capture_period_size = trial;
3775 }
3776 }
3777
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003778 pthread_mutex_unlock(&adev_init_lock);
3779
Eric Laurent994a6932013-07-17 11:51:42 -07003780 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 return 0;
3782}
3783
3784static struct hw_module_methods_t hal_module_methods = {
3785 .open = adev_open,
3786};
3787
3788struct audio_module HAL_MODULE_INFO_SYM = {
3789 .common = {
3790 .tag = HARDWARE_MODULE_TAG,
3791 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3792 .hal_api_version = HARDWARE_HAL_API_VERSION,
3793 .id = AUDIO_HARDWARE_MODULE_ID,
3794 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003795 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 .methods = &hal_module_methods,
3797 },
3798};