blob: 23238777125076bd46cdea8d5a044f6ba84dcd6e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
vivek mehtaa76401a2015-04-24 14:12:15 -0700255__attribute__ ((visibility ("default")))
256bool audio_hw_send_gain_dep_calibration(int level) {
257 bool ret_val = false;
258 ALOGV("%s: called ... ", __func__);
259
260 pthread_mutex_lock(&adev_init_lock);
261
262 if (adev != NULL && adev->platform != NULL) {
263 pthread_mutex_lock(&adev->lock);
264 ret_val = platform_send_gain_dep_cal(adev->platform, level);
265 pthread_mutex_unlock(&adev->lock);
266 } else {
267 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
268 }
269
270 pthread_mutex_unlock(&adev_init_lock);
271
272 return ret_val;
273}
274
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800275static int check_and_set_gapless_mode(struct audio_device *adev) {
276
277
278 char value[PROPERTY_VALUE_MAX] = {0};
279 bool gapless_enabled = false;
280 const char *mixer_ctl_name = "Compress Gapless Playback";
281 struct mixer_ctl *ctl;
282
283 ALOGV("%s:", __func__);
284 property_get("audio.offload.gapless.enabled", value, NULL);
285 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
286
287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
288 if (!ctl) {
289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
290 __func__, mixer_ctl_name);
291 return -EINVAL;
292 }
293
294 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
295 ALOGE("%s: Could not set gapless mode %d",
296 __func__, gapless_enabled);
297 return -EINVAL;
298 }
299 return 0;
300}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700302static bool is_supported_format(audio_format_t format)
303{
Eric Laurent86e17132013-09-12 17:49:30 -0700304 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 format == AUDIO_FORMAT_AAC_LC ||
306 format == AUDIO_FORMAT_AAC_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800310 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530311 format == AUDIO_FORMAT_ALAC ||
312 format == AUDIO_FORMAT_APE ||
313 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_WMA ||
315 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800316 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317
318 return false;
319}
320
321static int get_snd_codec_id(audio_format_t format)
322{
323 int id = 0;
324
Ashish Jainf9b78162014-08-25 20:36:25 +0530325 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700326 case AUDIO_FORMAT_MP3:
327 id = SND_AUDIOCODEC_MP3;
328 break;
329 case AUDIO_FORMAT_AAC:
330 id = SND_AUDIOCODEC_AAC;
331 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800333 id = SND_AUDIOCODEC_PCM;
334 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700335 case AUDIO_FORMAT_FLAC:
336 id = SND_AUDIOCODEC_FLAC;
337 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530338 case AUDIO_FORMAT_ALAC:
339 id = SND_AUDIOCODEC_ALAC;
340 break;
341 case AUDIO_FORMAT_APE:
342 id = SND_AUDIOCODEC_APE;
343 break;
344 case AUDIO_FORMAT_VORBIS:
345 id = SND_AUDIOCODEC_VORBIS;
346 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800347 case AUDIO_FORMAT_WMA:
348 id = SND_AUDIOCODEC_WMA;
349 break;
350 case AUDIO_FORMAT_WMA_PRO:
351 id = SND_AUDIOCODEC_WMA_PRO;
352 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700353 default:
Mingming Yin90310102013-11-13 16:57:00 -0800354 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700355 }
356
357 return id;
358}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800359
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530360int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530361{
362 int snd_scard_state;
363
364 if (!adev)
365 return SND_CARD_STATE_OFFLINE;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 snd_scard_state = adev->snd_card_status.state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return snd_scard_state;
372}
373
374static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
375{
376 if (!adev)
377 return -ENOSYS;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700380 if (adev->snd_card_status.state != snd_scard_state) {
381 adev->snd_card_status.state = snd_scard_state;
382 platform_snd_card_update(adev->platform, snd_scard_state);
383 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530384 pthread_mutex_unlock(&adev->snd_card_status.lock);
385
386 return 0;
387}
388
Avinash Vaish71a8b972014-07-24 15:36:33 +0530389static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
390 struct audio_usecase *uc_info)
391{
392 struct listnode *node;
393 struct audio_usecase *usecase;
394
395 if (uc_info == NULL)
396 return -EINVAL;
397
398 /* Re-route all voice usecases on the shared backend other than the
399 specified usecase to new snd devices */
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800402 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530403 enable_audio_route(adev, usecase);
404 }
405 return 0;
406}
407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700408int pcm_ioctl(struct pcm *pcm, int request, ...)
409{
410 va_list ap;
411 void * arg;
412 int pcm_fd = *(int*)pcm;
413
414 va_start(ap, request);
415 arg = va_arg(ap, void *);
416 va_end(ap);
417
418 return ioctl(pcm_fd, request, arg);
419}
420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700421int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700422 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700425 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426
427 if (usecase == NULL)
428 return -EINVAL;
429
430 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
431
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800434 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800437#ifdef DS1_DOLBY_DAP_ENABLED
438 audio_extn_dolby_set_dmid(adev);
439 audio_extn_dolby_set_endpoint(adev);
440#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700441 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530443 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700444 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700445 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700448 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
449 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 ALOGV("%s: exit", __func__);
451 return 0;
452}
453
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700454int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700455 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530460 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461 return -EINVAL;
462
463 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 if (usecase->type == PCM_CAPTURE)
465 snd_device = usecase->in_snd_device;
466 else
467 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700469 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700470 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
471 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700472 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530473 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700478int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800483 if (snd_device < SND_DEVICE_MIN ||
484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800486 return -EINVAL;
487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
489 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490
491 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
492 ALOGE("%s: Invalid sound device returned", __func__);
493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700496 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 return 0;
499 }
500
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700501 if (audio_extn_spkr_prot_is_enabled())
502 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 /* start usb playback thread */
504 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
505 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
506 audio_extn_usb_start_playback(adev);
507
508 /* start usb capture thread */
509 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
510 audio_extn_usb_start_capture(adev);
511
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800512 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
513 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700514 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700515 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
516 adev->snd_dev_ref_cnt[snd_device]--;
517 return -EINVAL;
518 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200519 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800520 if (audio_extn_spkr_prot_start_processing(snd_device)) {
521 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200522 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 return -EINVAL;
524 }
525 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
527 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700528 /* due to the possibility of calibration overwrite between listen
529 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700530 audio_extn_sound_trigger_update_device_status(snd_device,
531 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530532 audio_extn_listen_update_device_status(snd_device,
533 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700534 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700535 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 return -EINVAL;
541 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300542 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700543 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 return 0;
546}
547
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700548int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700549 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800553 if (snd_device < SND_DEVICE_MIN ||
554 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800555 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 return -EINVAL;
557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
559 ALOGE("%s: device ref cnt is already 0", __func__);
560 return -EINVAL;
561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700571 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800573 /* exit usb play back thread */
574 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
575 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
576 audio_extn_usb_stop_playback();
577
578 /* exit usb capture thread */
579 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700580 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800581
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
583 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700584 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700585 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700589
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200590 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700591 audio_extn_sound_trigger_update_device_status(snd_device,
592 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530593 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800594 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 return 0;
598}
599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600static void check_usecases_codec_backend(struct audio_device *adev,
601 struct audio_usecase *uc_info,
602 snd_device_t snd_device)
603{
604 struct listnode *node;
605 struct audio_usecase *usecase;
606 bool switch_device[AUDIO_USECASE_MAX];
607 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800608 int backend_idx = DEFAULT_CODEC_BACKEND;
609 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
611 /*
612 * This function is to make sure that all the usecases that are active on
613 * the hardware codec backend are always routed to any one device that is
614 * handled by the hardware codec.
615 * For example, if low-latency and deep-buffer usecases are currently active
616 * on speaker and out_set_parameters(headset) is received on low-latency
617 * output, then we have to make sure deep-buffer is also switched to headset,
618 * because of the limitation that both the devices cannot be enabled
619 * at the same time as they share the same backend.
620 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700621 /*
622 * This call is to check if we need to force routing for a particular stream
623 * If there is a backend configuration change for the device when a
624 * new stream starts, then ADM needs to be closed and re-opened with the new
625 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800626 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800628 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
629 snd_device);
630 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800632 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800633 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 for (i = 0; i < AUDIO_USECASE_MAX; i++)
635 switch_device[i] = false;
636
637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639
640 if (usecase == uc_info)
641 continue;
642 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
643 ALOGV("%s: backend_idx: %d,"
644 "usecase_backend_idx: %d, curr device: %s, usecase device:"
645 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530646 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800647
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800648 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700649 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
651 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530652 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700654 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700655 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 switch_device[usecase->id] = true;
657 num_uc_to_switch++;
658 }
659 }
660
661 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700662 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530664 /* Make sure the previous devices to be disabled first and then enable the
665 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
668 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
675 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700677 }
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 /* Re-route all the usecases on the shared backend other than the
681 specified usecase to new snd devices */
682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530684 /* Update the out_snd_device only for the usecases that are enabled here */
685 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
686 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530687 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 }
689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690 }
691}
692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693static void check_and_route_capture_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info,
695 snd_device_t snd_device)
696{
697 struct listnode *node;
698 struct audio_usecase *usecase;
699 bool switch_device[AUDIO_USECASE_MAX];
700 int i, num_uc_to_switch = 0;
701
702 /*
703 * This function is to make sure that all the active capture usecases
704 * are always routed to the same input sound device.
705 * For example, if audio-record and voice-call usecases are currently
706 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
707 * is received for voice call then we have to make sure that audio-record
708 * usecase is also switched to earpiece i.e. voice-dmic-ef,
709 * because of the limitation that two devices cannot be enabled
710 * at the same time if they share the same backend.
711 */
712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
713 switch_device[i] = false;
714
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700719 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700720 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
721 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700722 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700723 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
724 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700725 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 switch_device[usecase->id] = true;
728 num_uc_to_switch++;
729 }
730 }
731
732 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700733 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530735 /* Make sure the previous devices to be disabled first and then enable the
736 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800741 }
742 }
743
744 list_for_each(node, &adev->usecase_list) {
745 usecase = node_to_item(node, struct audio_usecase, list);
746 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 }
749 }
750
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 /* Re-route all the usecases on the shared backend other than the
752 specified usecase to new snd devices */
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 /* Update the in_snd_device only before enabling the audio route */
756 if (switch_device[usecase->id] ) {
757 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800758 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530759 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763}
764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700766static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700768 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700769 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770
771 switch (channels) {
772 /*
773 * Do not handle stereo output in Multi-channel cases
774 * Stereo case is handled in normal playback path
775 */
776 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 break;
784 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700785 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700794 ALOGE("HDMI does not support multi channel playback");
795 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796 break;
797 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700798 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799}
800
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800801audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
802 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800809 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700810 ALOGV("%s: usecase id %d", __func__, usecase->id);
811 return usecase->id;
812 }
813 }
814 return USECASE_INVALID;
815}
816
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700817struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
825 if (usecase->id == uc_id)
826 return usecase;
827 }
828 return NULL;
829}
830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700831int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800833 snd_device_t out_snd_device = SND_DEVICE_NONE;
834 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 struct audio_usecase *usecase = NULL;
836 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800837 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800838 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800839 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800840 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 usecase = get_usecase_from_list(adev, uc_id);
844 if (usecase == NULL) {
845 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
846 return -EINVAL;
847 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800850 (usecase->type == VOIP_CALL) ||
851 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700852 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800853 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700854 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase->devices = usecase->stream.out->devices;
856 } else {
857 /*
858 * If the voice call is active, use the sound devices of voice call usecase
859 * so that it would not result any device switch. All the usecases will
860 * be switched to new device when select_devices() is called for voice call
861 * usecase. This is to avoid switching devices for voice call when
862 * check_usecases_codec_backend() is called below.
863 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700864 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700865 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800866 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
868 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 in_snd_device = vc_usecase->in_snd_device;
870 out_snd_device = vc_usecase->out_snd_device;
871 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800872 } else if (voice_extn_compress_voip_is_active(adev)) {
873 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700874 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530875 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 in_snd_device = voip_usecase->in_snd_device;
878 out_snd_device = voip_usecase->out_snd_device;
879 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800880 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800881 hfp_ucid = audio_extn_hfp_get_usecase();
882 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800884 in_snd_device = hfp_usecase->in_snd_device;
885 out_snd_device = hfp_usecase->out_snd_device;
886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 }
888 if (usecase->type == PCM_PLAYBACK) {
889 usecase->devices = usecase->stream.out->devices;
890 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700892 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800893 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700894 if (usecase->stream.out == adev->primary_output &&
895 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800896 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 select_devices(adev, adev->active_input->usecase);
898 }
899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 } else if (usecase->type == PCM_CAPTURE) {
901 usecase->devices = usecase->stream.in->device;
902 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700904 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530905 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
906 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
907 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
908 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700909 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
912 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700914 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 }
917 }
918
919 if (out_snd_device == usecase->out_snd_device &&
920 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922 }
923
sangwoobc677242013-08-08 16:53:43 +0900924 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700925 out_snd_device, platform_get_snd_device_name(out_snd_device),
926 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 /*
929 * Limitation: While in call, to do a device switch we need to disable
930 * and enable both RX and TX devices though one of them is same as current
931 * device.
932 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700933 if ((usecase->type == VOICE_CALL) &&
934 (usecase->in_snd_device != SND_DEVICE_NONE) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700937 }
938
939 if (((usecase->type == VOICE_CALL) ||
940 (usecase->type == VOIP_CALL)) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
942 /* Disable sidetone only if voice/voip call already exists */
943 if (voice_is_call_state_active(adev) ||
944 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700945 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 /* Disable current sound devices */
949 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700950 disable_audio_route(adev, usecase);
951 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700955 disable_audio_route(adev, usecase);
956 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957 }
958
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800959 /* Applicable only on the targets that has external modem.
960 * New device information should be sent to modem before enabling
961 * the devices to reduce in-call device switch time.
962 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 if ((usecase->type == VOICE_CALL) &&
964 (usecase->in_snd_device != SND_DEVICE_NONE) &&
965 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800966 status = platform_switch_voice_call_enable_device_config(adev->platform,
967 out_snd_device,
968 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700969 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Enable new sound devices */
972 if (out_snd_device != SND_DEVICE_NONE) {
973 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
974 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700975 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976 }
977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700978 if (in_snd_device != SND_DEVICE_NONE) {
979 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700981 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982
Avinash Vaish71a8b972014-07-24 15:36:33 +0530983 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700984 status = platform_switch_voice_call_device_post(adev->platform,
985 out_snd_device,
986 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530987 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700988 /* Enable sidetone only if voice/voip call already exists */
989 if (voice_is_call_state_active(adev) ||
990 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700991 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800993
sangwoo170731f2013-06-08 15:36:36 +0900994 usecase->in_snd_device = in_snd_device;
995 usecase->out_snd_device = out_snd_device;
996
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530997 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700998 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530999 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 usecase->stream.out->flags,
1002 usecase->stream.out->format,
1003 usecase->stream.out->sample_rate,
1004 usecase->stream.out->bit_width,
1005 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001006 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301007 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001008
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001009 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001010
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001011 /* Applicable only on the targets that has external modem.
1012 * Enable device command should be sent to modem only after
1013 * enabling voice call mixer controls
1014 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001015 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001016 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1017 out_snd_device,
1018 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301019 ALOGD("%s: done",__func__);
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 return status;
1022}
1023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024static int stop_input_stream(struct stream_in *in)
1025{
1026 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 struct audio_usecase *uc_info;
1028 struct audio_device *adev = in->dev;
1029
Eric Laurentc8400632013-02-14 19:04:54 -08001030 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031
Eric Laurent994a6932013-07-17 11:51:42 -07001032 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 uc_info = get_usecase_from_list(adev, in->usecase);
1035 if (uc_info == NULL) {
1036 ALOGE("%s: Could not find the usecase (%d) in the list",
1037 __func__, in->usecase);
1038 return -EINVAL;
1039 }
1040
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001041 /* Close in-call recording streams */
1042 voice_check_and_stop_incall_rec_usecase(adev, in);
1043
Eric Laurent150dbfe2013-02-27 14:31:02 -08001044 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001045 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046
1047 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001048 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001050 list_remove(&uc_info->list);
1051 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052
Eric Laurent994a6932013-07-17 11:51:42 -07001053 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 return ret;
1055}
1056
1057int start_input_stream(struct stream_in *in)
1058{
1059 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 struct audio_usecase *uc_info;
1062 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301063 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Mingming Yin2664a5b2015-09-03 10:53:11 -07001065 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1066 if (get_usecase_from_list(adev, usecase) == NULL)
1067 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301068 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1069 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001070
Naresh Tanniru80659832014-06-04 18:17:56 +05301071
1072 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301073 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301074 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301075 goto error_config;
1076 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301077
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001078 /* Check if source matches incall recording usecase criteria */
1079 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1080 if (ret)
1081 goto error_config;
1082 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001083 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1084
1085 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1086 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1087 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1088 goto error_config;
1089 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001090
Eric Laurentb23d5282013-05-14 15:27:20 -07001091 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092 if (in->pcm_device_id < 0) {
1093 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1094 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001095 ret = -EINVAL;
1096 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098
1099 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001101
1102 if (!uc_info) {
1103 ret = -ENOMEM;
1104 goto error_config;
1105 }
1106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 uc_info->id = in->usecase;
1108 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001109 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 uc_info->devices = in->device;
1111 uc_info->in_snd_device = SND_DEVICE_NONE;
1112 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001114 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301115 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Eric Laurentc8400632013-02-14 19:04:54 -08001118 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001119 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1120
1121 unsigned int flags = PCM_IN;
1122 unsigned int pcm_open_retry_count = 0;
1123
1124 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1125 flags |= PCM_MMAP | PCM_NOIRQ;
1126 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1127 }
1128
1129 while (1) {
1130 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1131 flags, &in->config);
1132 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1133 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1134 if (in->pcm != NULL) {
1135 pcm_close(in->pcm);
1136 in->pcm = NULL;
1137 }
1138 if (pcm_open_retry_count-- == 0) {
1139 ret = -EIO;
1140 goto error_open;
1141 }
1142 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1143 continue;
1144 }
1145 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301147 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301148
Eric Laurent994a6932013-07-17 11:51:42 -07001149 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001150 return ret;
1151
1152error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301154 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001155
1156error_config:
1157 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001159
1160 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161}
1162
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001163/* must be called with out->lock locked */
1164static int send_offload_cmd_l(struct stream_out* out, int command)
1165{
1166 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1167
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001168 if (!cmd) {
1169 ALOGE("failed to allocate mem for command 0x%x", command);
1170 return -ENOMEM;
1171 }
1172
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001173 ALOGVV("%s %d", __func__, command);
1174
1175 cmd->cmd = command;
1176 list_add_tail(&out->offload_cmd_list, &cmd->node);
1177 pthread_cond_signal(&out->offload_cond);
1178 return 0;
1179}
1180
1181/* must be called iwth out->lock locked */
1182static void stop_compressed_output_l(struct stream_out *out)
1183{
1184 out->offload_state = OFFLOAD_STATE_IDLE;
1185 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001186 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187 if (out->compr != NULL) {
1188 compress_stop(out->compr);
1189 while (out->offload_thread_blocked) {
1190 pthread_cond_wait(&out->cond, &out->lock);
1191 }
1192 }
1193}
1194
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001195bool is_offload_usecase(audio_usecase_t uc_id)
1196{
1197 unsigned int i;
1198 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1199 if (uc_id == offload_usecases[i])
1200 return true;
1201 }
1202 return false;
1203}
1204
1205static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1206{
1207 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1208 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1209 char value[PROPERTY_VALUE_MAX] = {0};
1210
1211 property_get("audio.offload.multiple.enabled", value, NULL);
1212 if (!(atoi(value) || !strncmp("true", value, 4)))
1213 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1214
1215 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1216 for (i = 0; i < num_usecase; i++) {
1217 if (!(adev->offload_usecases_state & (0x1<<i))) {
1218 adev->offload_usecases_state |= 0x1 << i;
1219 ret = offload_usecases[i];
1220 break;
1221 }
1222 }
1223 ALOGV("%s: offload usecase is %d", __func__, ret);
1224 return ret;
1225}
1226
1227static void free_offload_usecase(struct audio_device *adev,
1228 audio_usecase_t uc_id)
1229{
1230 unsigned int i;
1231 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1232 if (offload_usecases[i] == uc_id) {
1233 adev->offload_usecases_state &= ~(0x1<<i);
1234 break;
1235 }
1236 }
1237 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1238}
1239
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240static void *offload_thread_loop(void *context)
1241{
1242 struct stream_out *out = (struct stream_out *) context;
1243 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001244 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001246 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1247 set_sched_policy(0, SP_FOREGROUND);
1248 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1249
1250 ALOGV("%s", __func__);
1251 pthread_mutex_lock(&out->lock);
1252 for (;;) {
1253 struct offload_cmd *cmd = NULL;
1254 stream_callback_event_t event;
1255 bool send_callback = false;
1256
1257 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1258 __func__, list_empty(&out->offload_cmd_list),
1259 out->offload_state);
1260 if (list_empty(&out->offload_cmd_list)) {
1261 ALOGV("%s SLEEPING", __func__);
1262 pthread_cond_wait(&out->offload_cond, &out->lock);
1263 ALOGV("%s RUNNING", __func__);
1264 continue;
1265 }
1266
1267 item = list_head(&out->offload_cmd_list);
1268 cmd = node_to_item(item, struct offload_cmd, node);
1269 list_remove(item);
1270
1271 ALOGVV("%s STATE %d CMD %d out->compr %p",
1272 __func__, out->offload_state, cmd->cmd, out->compr);
1273
1274 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1275 free(cmd);
1276 break;
1277 }
1278
1279 if (out->compr == NULL) {
1280 ALOGE("%s: Compress handle is NULL", __func__);
1281 pthread_cond_signal(&out->cond);
1282 continue;
1283 }
1284 out->offload_thread_blocked = true;
1285 pthread_mutex_unlock(&out->lock);
1286 send_callback = false;
1287 switch(cmd->cmd) {
1288 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001289 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 send_callback = true;
1293 event = STREAM_CBK_EVENT_WRITE_READY;
1294 break;
1295 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001296 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301297 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001298 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301299 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001300 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301301 if (ret < 0)
1302 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301303 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301304 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001305 compress_drain(out->compr);
1306 else
1307 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301308 if (ret != -ENETRESET) {
1309 send_callback = true;
1310 event = STREAM_CBK_EVENT_DRAIN_READY;
1311 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1312 } else
1313 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 break;
1315 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001316 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001318 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 send_callback = true;
1320 event = STREAM_CBK_EVENT_DRAIN_READY;
1321 break;
1322 default:
1323 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1324 break;
1325 }
1326 pthread_mutex_lock(&out->lock);
1327 out->offload_thread_blocked = false;
1328 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001329 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001330 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001331 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001332 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001333 free(cmd);
1334 }
1335
1336 pthread_cond_signal(&out->cond);
1337 while (!list_empty(&out->offload_cmd_list)) {
1338 item = list_head(&out->offload_cmd_list);
1339 list_remove(item);
1340 free(node_to_item(item, struct offload_cmd, node));
1341 }
1342 pthread_mutex_unlock(&out->lock);
1343
1344 return NULL;
1345}
1346
1347static int create_offload_callback_thread(struct stream_out *out)
1348{
1349 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1350 list_init(&out->offload_cmd_list);
1351 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1352 offload_thread_loop, out);
1353 return 0;
1354}
1355
1356static int destroy_offload_callback_thread(struct stream_out *out)
1357{
1358 pthread_mutex_lock(&out->lock);
1359 stop_compressed_output_l(out);
1360 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1361
1362 pthread_mutex_unlock(&out->lock);
1363 pthread_join(out->offload_thread, (void **) NULL);
1364 pthread_cond_destroy(&out->offload_cond);
1365
1366 return 0;
1367}
1368
Eric Laurent07eeafd2013-10-06 12:52:49 -07001369static bool allow_hdmi_channel_config(struct audio_device *adev)
1370{
1371 struct listnode *node;
1372 struct audio_usecase *usecase;
1373 bool ret = true;
1374
1375 list_for_each(node, &adev->usecase_list) {
1376 usecase = node_to_item(node, struct audio_usecase, list);
1377 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1378 /*
1379 * If voice call is already existing, do not proceed further to avoid
1380 * disabling/enabling both RX and TX devices, CSD calls, etc.
1381 * Once the voice call done, the HDMI channels can be configured to
1382 * max channels of remaining use cases.
1383 */
1384 if (usecase->id == USECASE_VOICE_CALL) {
1385 ALOGD("%s: voice call is active, no change in HDMI channels",
1386 __func__);
1387 ret = false;
1388 break;
1389 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1390 ALOGD("%s: multi channel playback is active, "
1391 "no change in HDMI channels", __func__);
1392 ret = false;
1393 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001394 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001395 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001396 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1397 ", no change in HDMI channels", __func__,
1398 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001399 ret = false;
1400 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 }
1402 }
1403 }
1404 return ret;
1405}
1406
1407static int check_and_set_hdmi_channels(struct audio_device *adev,
1408 unsigned int channels)
1409{
1410 struct listnode *node;
1411 struct audio_usecase *usecase;
1412
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001413 unsigned int supported_channels = platform_edid_get_max_channels(
1414 adev->platform);
1415 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 /* Check if change in HDMI channel config is allowed */
1417 if (!allow_hdmi_channel_config(adev))
1418 return 0;
1419
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001420 if (channels > supported_channels)
1421 channels = supported_channels;
1422
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001424 ALOGD("%s: Requested channels are same as current channels(%d)",
1425 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001426 return 0;
1427 }
1428
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001429 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001431 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432 adev->cur_hdmi_channels = channels;
1433
1434 /*
1435 * Deroute all the playback streams routed to HDMI so that
1436 * the back end is deactivated. Note that backend will not
1437 * be deactivated if any one stream is connected to it.
1438 */
1439 list_for_each(node, &adev->usecase_list) {
1440 usecase = node_to_item(node, struct audio_usecase, list);
1441 if (usecase->type == PCM_PLAYBACK &&
1442 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001443 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001444 }
1445 }
1446
1447 /*
1448 * Enable all the streams disabled above. Now the HDMI backend
1449 * will be activated with new channel configuration
1450 */
1451 list_for_each(node, &adev->usecase_list) {
1452 usecase = node_to_item(node, struct audio_usecase, list);
1453 if (usecase->type == PCM_PLAYBACK &&
1454 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001455 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001456 }
1457 }
1458
1459 return 0;
1460}
1461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462static int stop_output_stream(struct stream_out *out)
1463{
1464 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 struct audio_usecase *uc_info;
1466 struct audio_device *adev = out->dev;
1467
Eric Laurent994a6932013-07-17 11:51:42 -07001468 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 uc_info = get_usecase_from_list(adev, out->usecase);
1471 if (uc_info == NULL) {
1472 ALOGE("%s: Could not find the usecase (%d) in the list",
1473 __func__, out->usecase);
1474 return -EINVAL;
1475 }
1476
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001477 if (is_offload_usecase(out->usecase) &&
1478 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001479 if (adev->visualizer_stop_output != NULL)
1480 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001481
1482 audio_extn_dts_remove_state_notifier_node(out->usecase);
1483
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001484 if (adev->offload_effects_stop_output != NULL)
1485 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1486 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001487
Eric Laurent150dbfe2013-02-27 14:31:02 -08001488 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001489 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001490
1491 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001492 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001494 list_remove(&uc_info->list);
1495 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001497 if (is_offload_usecase(out->usecase) &&
1498 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1499 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1500 ALOGV("Disable passthrough , reset mixer to pcm");
1501 /* NO_PASSTHROUGH */
1502 out->compr_config.codec->compr_passthr = 0;
1503 audio_extn_dolby_set_hdmi_config(adev, out);
1504 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1505 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001506 /* Must be called after removing the usecase from list */
1507 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1508 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1509
Eric Laurent994a6932013-07-17 11:51:42 -07001510 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 return ret;
1512}
1513
1514int start_output_stream(struct stream_out *out)
1515{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001517 int sink_channels = 0;
1518 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 struct audio_usecase *uc_info;
1520 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301521 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001523 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1524 ret = -EINVAL;
1525 goto error_config;
1526 }
1527
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301528 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1529 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1530 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301531
Naresh Tanniru80659832014-06-04 18:17:56 +05301532 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301533 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301534 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301535 goto error_config;
1536 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301537
Eric Laurentb23d5282013-05-14 15:27:20 -07001538 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 if (out->pcm_device_id < 0) {
1540 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1541 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001542 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001543 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 }
1545
1546 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001547
1548 if (!uc_info) {
1549 ret = -ENOMEM;
1550 goto error_config;
1551 }
1552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 uc_info->id = out->usecase;
1554 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001555 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 uc_info->devices = out->devices;
1557 uc_info->in_snd_device = SND_DEVICE_NONE;
1558 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001559 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001560 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001561 if (is_offload_usecase(out->usecase)) {
1562 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001563 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1564 }
1565 }
Mingming Yin9c041392014-05-01 15:37:31 -07001566 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1567 if (!strncmp("true", prop_value, 4)) {
1568 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001569 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1570 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001571 check_and_set_hdmi_channels(adev, sink_channels);
1572 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001573 if (is_offload_usecase(out->usecase)) {
1574 unsigned int ch_count = out->compr_config.codec->ch_in;
1575 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1576 /* backend channel config for passthrough stream is stereo */
1577 ch_count = 2;
1578 check_and_set_hdmi_channels(adev, ch_count);
1579 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001580 check_and_set_hdmi_channels(adev, out->config.channels);
1581 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001582 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001583 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001584 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001586 select_devices(adev, out->usecase);
1587
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001588 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1589 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001590 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 unsigned int flags = PCM_OUT;
1592 unsigned int pcm_open_retry_count = 0;
1593 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1594 flags |= PCM_MMAP | PCM_NOIRQ;
1595 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1596 } else
1597 flags |= PCM_MONOTONIC;
1598
1599 while (1) {
1600 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1601 flags, &out->config);
1602 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1603 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1604 if (out->pcm != NULL) {
1605 pcm_close(out->pcm);
1606 out->pcm = NULL;
1607 }
1608 if (pcm_open_retry_count-- == 0) {
1609 ret = -EIO;
1610 goto error_open;
1611 }
1612 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1613 continue;
1614 }
1615 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001616 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001617 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1618 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001619 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001620 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1621 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001623 out->compr = compress_open(adev->snd_card,
1624 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001625 COMPRESS_IN, &out->compr_config);
1626 if (out->compr && !is_compress_ready(out->compr)) {
1627 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1628 compress_close(out->compr);
1629 out->compr = NULL;
1630 ret = -EIO;
1631 goto error_open;
1632 }
1633 if (out->offload_callback)
1634 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001635
Fred Oh3f43e742015-03-04 18:42:34 -08001636 /* Since small bufs uses blocking writes, a write will be blocked
1637 for the default max poll time (20s) in the event of an SSR.
1638 Reduce the poll time to observe and deal with SSR faster.
1639 */
1640 if (out->use_small_bufs) {
1641 compress_set_max_poll_wait(out->compr, 1000);
1642 }
1643
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001644 audio_extn_dts_create_state_notifier_node(out->usecase);
1645 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1646 popcount(out->channel_mask),
1647 out->playback_started);
1648
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001649#ifdef DS1_DOLBY_DDP_ENABLED
1650 if (audio_extn_is_dolby_format(out->format))
1651 audio_extn_dolby_send_ddp_endp_params(adev);
1652#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001653 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1654 if (adev->visualizer_start_output != NULL)
1655 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1656 if (adev->offload_effects_start_output != NULL)
1657 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001658 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 }
Eric Laurent994a6932013-07-17 11:51:42 -07001661 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001663error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001665error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001666 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667}
1668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669static int check_input_parameters(uint32_t sample_rate,
1670 audio_format_t format,
1671 int channel_count)
1672{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001673 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001675 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001676 !voice_extn_compress_voip_is_format_supported(format) &&
1677 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001678
1679 switch (channel_count) {
1680 case 1:
1681 case 2:
1682 case 6:
1683 break;
1684 default:
1685 ret = -EINVAL;
1686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687
1688 switch (sample_rate) {
1689 case 8000:
1690 case 11025:
1691 case 12000:
1692 case 16000:
1693 case 22050:
1694 case 24000:
1695 case 32000:
1696 case 44100:
1697 case 48000:
1698 break;
1699 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001700 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 }
1702
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001703 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704}
1705
1706static size_t get_input_buffer_size(uint32_t sample_rate,
1707 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001708 int channel_count,
1709 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710{
1711 size_t size = 0;
1712
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001713 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1714 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001716 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001717 if (is_low_latency)
1718 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001719 /* ToDo: should use frame_size computed based on the format and
1720 channel_count here. */
1721 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001723 /* make sure the size is multiple of 32 bytes
1724 * At 48 kHz mono 16-bit PCM:
1725 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1726 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1727 */
1728 size += 0x1f;
1729 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001730
1731 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732}
1733
1734static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1735{
1736 struct stream_out *out = (struct stream_out *)stream;
1737
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739}
1740
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001741static int out_set_sample_rate(struct audio_stream *stream __unused,
1742 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743{
1744 return -ENOSYS;
1745}
1746
1747static size_t out_get_buffer_size(const struct audio_stream *stream)
1748{
1749 struct stream_out *out = (struct stream_out *)stream;
1750
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001751 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001753 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1754 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001756 return out->config.period_size *
1757 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758}
1759
1760static uint32_t out_get_channels(const struct audio_stream *stream)
1761{
1762 struct stream_out *out = (struct stream_out *)stream;
1763
1764 return out->channel_mask;
1765}
1766
1767static audio_format_t out_get_format(const struct audio_stream *stream)
1768{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769 struct stream_out *out = (struct stream_out *)stream;
1770
1771 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772}
1773
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001774static int out_set_format(struct audio_stream *stream __unused,
1775 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776{
1777 return -ENOSYS;
1778}
1779
1780static int out_standby(struct audio_stream *stream)
1781{
1782 struct stream_out *out = (struct stream_out *)stream;
1783 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301785 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1786 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001787 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1788 /* Ignore standby in case of voip call because the voip output
1789 * stream is closed in adev_close_output_stream()
1790 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301791 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001792 return 0;
1793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001797 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001799 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 if (out->pcm) {
1801 pcm_close(out->pcm);
1802 out->pcm = NULL;
1803 }
1804 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001805 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807 out->gapless_mdata.encoder_delay = 0;
1808 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001809 if (out->compr != NULL) {
1810 compress_close(out->compr);
1811 out->compr = NULL;
1812 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001815 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 }
1817 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001818 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819 return 0;
1820}
1821
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001822static int out_dump(const struct audio_stream *stream __unused,
1823 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824{
1825 return 0;
1826}
1827
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001828static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1829{
1830 int ret = 0;
1831 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001832 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001833
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001835 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836 return -EINVAL;
1837 }
1838
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001839 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1840 if (ret >= 0) {
1841 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1842 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1843 ALOGV("ADTS format is set in offload mode");
1844 }
1845 out->send_new_metadata = 1;
1846 }
1847
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301848 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001849
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001850 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1851 if(ret >= 0)
1852 is_meta_data_params = true;
1853 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301854 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001855 is_meta_data_params = true;
1856 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301857 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001858 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1860 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001861 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301862 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001863 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1865 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001866 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301867 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001868 }
1869
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001870 if(!is_meta_data_params) {
1871 ALOGV("%s: Not gapless meta data params", __func__);
1872 return 0;
1873 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 out->send_new_metadata = 1;
1875 ALOGV("%s new encoder delay %u and padding %u", __func__,
1876 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1877
1878 return 0;
1879}
1880
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001881static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1882{
1883 return out == adev->primary_output || out == adev->voice_tx_output;
1884}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1887{
1888 struct stream_out *out = (struct stream_out *)stream;
1889 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001890 struct audio_usecase *usecase;
1891 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 struct str_parms *parms;
1893 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001894 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001895 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896
sangwoobc677242013-08-08 16:53:43 +09001897 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301900 if (!parms)
1901 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001902 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1903 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001906 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301909 * When HDMI cable is unplugged/usb hs is disconnected the
1910 * music playback is paused and the policy manager sends routing=0
1911 * But the audioflingercontinues to write data until standby time
1912 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 * Avoid this by routing audio to speaker until standby.
1914 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301915 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1916 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001917 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001918 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1919 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001920 }
1921
1922 /*
1923 * select_devices() call below switches all the usecases on the same
1924 * backend to the new device. Refer to check_usecases_codec_backend() in
1925 * the select_devices(). But how do we undo this?
1926 *
1927 * For example, music playback is active on headset (deep-buffer usecase)
1928 * and if we go to ringtones and select a ringtone, low-latency usecase
1929 * will be started on headset+speaker. As we can't enable headset+speaker
1930 * and headset devices at the same time, select_devices() switches the music
1931 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1932 * So when the ringtone playback is completed, how do we undo the same?
1933 *
1934 * We are relying on the out_set_parameters() call on deep-buffer output,
1935 * once the ringtone playback is ended.
1936 * NOTE: We should not check if the current devices are same as new devices.
1937 * Because select_devices() must be called to switch back the music
1938 * playback to headset.
1939 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001940 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001941 out->devices = val;
1942
1943 if (!out->standby)
1944 select_devices(adev, out->usecase);
1945
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001946 if (output_drives_call(adev, out)) {
1947 if(!voice_is_in_call(adev)) {
1948 if (adev->mode == AUDIO_MODE_IN_CALL) {
1949 adev->current_call_output = out;
1950 ret = voice_start_call(adev);
1951 }
1952 } else {
1953 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001954 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001955 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001956 }
1957 }
1958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001960 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001962
1963 if (out == adev->primary_output) {
1964 pthread_mutex_lock(&adev->lock);
1965 audio_extn_set_parameters(adev, parms);
1966 pthread_mutex_unlock(&adev->lock);
1967 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001968 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001969 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001970 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001971
1972 audio_extn_dts_create_state_notifier_node(out->usecase);
1973 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1974 popcount(out->channel_mask),
1975 out->playback_started);
1976
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001977 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001978 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301981error:
Eric Laurent994a6932013-07-17 11:51:42 -07001982 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 return ret;
1984}
1985
1986static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1987{
1988 struct stream_out *out = (struct stream_out *)stream;
1989 struct str_parms *query = str_parms_create_str(keys);
1990 char *str;
1991 char value[256];
1992 struct str_parms *reply = str_parms_create();
1993 size_t i, j;
1994 int ret;
1995 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001996
1997 if (!query || !reply) {
1998 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1999 return NULL;
2000 }
2001
Eric Laurent994a6932013-07-17 11:51:42 -07002002 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2004 if (ret >= 0) {
2005 value[0] = '\0';
2006 i = 0;
2007 while (out->supported_channel_masks[i] != 0) {
2008 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2009 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2010 if (!first) {
2011 strcat(value, "|");
2012 }
2013 strcat(value, out_channels_name_to_enum_table[j].name);
2014 first = false;
2015 break;
2016 }
2017 }
2018 i++;
2019 }
2020 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2021 str = str_parms_to_str(reply);
2022 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002023 voice_extn_out_get_parameters(out, query, reply);
2024 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002025 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002026 free(str);
2027 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002030
2031 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2032 if (ret >= 0) {
2033 value[0] = '\0';
2034 i = 0;
2035 first = true;
2036 while (out->supported_formats[i] != 0) {
2037 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2038 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2039 if (!first) {
2040 strcat(value, "|");
2041 }
2042 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2043 first = false;
2044 break;
2045 }
2046 }
2047 i++;
2048 }
2049 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2050 str = str_parms_to_str(reply);
2051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 str_parms_destroy(query);
2053 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002054 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 return str;
2056}
2057
2058static uint32_t out_get_latency(const struct audio_stream_out *stream)
2059{
2060 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002061 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062
Alexy Josephaa54c872014-12-03 02:46:47 -08002063 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002064 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002065 } else {
2066 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002068 }
2069
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302070 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002071 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072}
2073
2074static int out_set_volume(struct audio_stream_out *stream, float left,
2075 float right)
2076{
Eric Laurenta9024de2013-04-04 09:19:12 -07002077 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 int volume[2];
2079
Eric Laurenta9024de2013-04-04 09:19:12 -07002080 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2081 /* only take left channel into account: the API is for stereo anyway */
2082 out->muted = (left == 0.0f);
2083 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002084 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002085 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2086 /*
2087 * Set mute or umute on HDMI passthrough stream.
2088 * Only take left channel into account.
2089 * Mute is 0 and unmute 1
2090 */
2091 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2092 } else {
2093 char mixer_ctl_name[128];
2094 struct audio_device *adev = out->dev;
2095 struct mixer_ctl *ctl;
2096 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002097 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002099 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2100 "Compress Playback %d Volume", pcm_device_id);
2101 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2102 if (!ctl) {
2103 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2104 __func__, mixer_ctl_name);
2105 return -EINVAL;
2106 }
2107 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2108 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2109 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2110 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002112 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 return -ENOSYS;
2115}
2116
2117static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2118 size_t bytes)
2119{
2120 struct stream_out *out = (struct stream_out *)stream;
2121 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302122 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002123 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302126
Naresh Tanniru80659832014-06-04 18:17:56 +05302127 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002128 // increase written size during SSR to avoid mismatch
2129 // with the written frames count in AF
2130 if (!is_offload_usecase(out->usecase))
2131 out->written += bytes / (out->config.channels * sizeof(short));
2132
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302134 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302135 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302136 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002137 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302138 //during SSR for compress usecase we should return error to flinger
2139 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2140 pthread_mutex_unlock(&out->lock);
2141 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142 }
2143 }
2144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002146 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002147 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002148 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2149 ret = voice_extn_compress_voip_start_output_stream(out);
2150 else
2151 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002152 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002155 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 goto exit;
2157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002160 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002161 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002163 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002164 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2165 out->send_new_metadata = 0;
2166 }
2167
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302169 if (ret < 0)
2170 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002171 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002172 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302173 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302175 } else if (-ENETRESET == ret) {
2176 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2177 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2178 pthread_mutex_unlock(&out->lock);
2179 out_standby(&out->stream.common);
2180 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302182 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002184 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 out->playback_started = 1;
2186 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002187
2188 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2189 popcount(out->channel_mask),
2190 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 }
2192 pthread_mutex_unlock(&out->lock);
2193 return ret;
2194 } else {
2195 if (out->pcm) {
2196 if (out->muted)
2197 memset((void *)buffer, 0, bytes);
2198 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002199 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2200 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2201 else
2202 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302203 if (ret < 0)
2204 ret = -errno;
2205 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002206 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 }
2209
2210exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302211 /* ToDo: There may be a corner case when SSR happens back to back during
2212 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302213 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302214 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302215 }
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 pthread_mutex_unlock(&out->lock);
2218
2219 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002220 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002221 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302222 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302223 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302224 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302225 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302226 out->standby = true;
2227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002229 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302230 out_get_sample_rate(&out->stream.common));
2231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 }
2233 return bytes;
2234}
2235
2236static int out_get_render_position(const struct audio_stream_out *stream,
2237 uint32_t *dsp_frames)
2238{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302240 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002241
2242 if (dsp_frames == NULL)
2243 return -EINVAL;
2244
2245 *dsp_frames = 0;
2246 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002247 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 pthread_mutex_lock(&out->lock);
2249 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302250 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302252 if (ret < 0)
2253 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 ALOGVV("%s rendered frames %d sample_rate %d",
2255 __func__, *dsp_frames, out->sample_rate);
2256 }
2257 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302258 if (-ENETRESET == ret) {
2259 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2260 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2261 return -EINVAL;
2262 } else if(ret < 0) {
2263 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2264 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302265 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2266 /*
2267 * Handle corner case where compress session is closed during SSR
2268 * and timestamp is queried
2269 */
2270 ALOGE(" ERROR: sound card not active, return error");
2271 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302272 } else {
2273 return 0;
2274 }
Zhou Song32a556e2015-05-05 10:46:56 +08002275 } else if (audio_is_linear_pcm(out->format)) {
2276 *dsp_frames = out->written;
2277 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 } else
2279 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280}
2281
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002282static int out_add_audio_effect(const struct audio_stream *stream __unused,
2283 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284{
2285 return 0;
2286}
2287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002288static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2289 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290{
2291 return 0;
2292}
2293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002294static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2295 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296{
2297 return -EINVAL;
2298}
2299
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002300static int out_get_presentation_position(const struct audio_stream_out *stream,
2301 uint64_t *frames, struct timespec *timestamp)
2302{
2303 struct stream_out *out = (struct stream_out *)stream;
2304 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002305 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002306
2307 pthread_mutex_lock(&out->lock);
2308
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002309 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002310 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302311 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002312 &out->sample_rate);
2313 ALOGVV("%s rendered frames %ld sample_rate %d",
2314 __func__, dsp_frames, out->sample_rate);
2315 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302316 if (ret < 0)
2317 ret = -errno;
2318 if (-ENETRESET == ret) {
2319 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2320 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2321 ret = -EINVAL;
2322 } else
2323 ret = 0;
2324
Eric Laurent949a0892013-09-20 09:20:13 -07002325 /* this is the best we can do */
2326 clock_gettime(CLOCK_MONOTONIC, timestamp);
2327 }
2328 } else {
2329 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002330 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002331 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2332 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002333 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002334 // This adjustment accounts for buffering after app processor.
2335 // It is based on estimated DSP latency per use case, rather than exact.
2336 signed_frames -=
2337 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2338
Eric Laurent949a0892013-09-20 09:20:13 -07002339 // It would be unusual for this value to be negative, but check just in case ...
2340 if (signed_frames >= 0) {
2341 *frames = signed_frames;
2342 ret = 0;
2343 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002344 }
2345 }
2346 }
2347
2348 pthread_mutex_unlock(&out->lock);
2349
2350 return ret;
2351}
2352
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353static int out_set_callback(struct audio_stream_out *stream,
2354 stream_callback_t callback, void *cookie)
2355{
2356 struct stream_out *out = (struct stream_out *)stream;
2357
2358 ALOGV("%s", __func__);
2359 pthread_mutex_lock(&out->lock);
2360 out->offload_callback = callback;
2361 out->offload_cookie = cookie;
2362 pthread_mutex_unlock(&out->lock);
2363 return 0;
2364}
2365
2366static int out_pause(struct audio_stream_out* stream)
2367{
2368 struct stream_out *out = (struct stream_out *)stream;
2369 int status = -ENOSYS;
2370 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002371 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002372 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 pthread_mutex_lock(&out->lock);
2374 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302375 struct audio_device *adev = out->dev;
2376 int snd_scard_state = get_snd_card_state(adev);
2377
2378 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2379 status = compress_pause(out->compr);
2380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002382
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302383 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002384 audio_extn_dts_notify_playback_state(out->usecase, 0,
2385 out->sample_rate, popcount(out->channel_mask),
2386 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 }
2388 pthread_mutex_unlock(&out->lock);
2389 }
2390 return status;
2391}
2392
2393static int out_resume(struct audio_stream_out* stream)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 int status = -ENOSYS;
2397 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002398 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002399 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 status = 0;
2401 pthread_mutex_lock(&out->lock);
2402 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302403 struct audio_device *adev = out->dev;
2404 int snd_scard_state = get_snd_card_state(adev);
2405
2406 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2407 status = compress_resume(out->compr);
2408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002410
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302411 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002412 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2413 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 }
2415 pthread_mutex_unlock(&out->lock);
2416 }
2417 return status;
2418}
2419
2420static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423 int status = -ENOSYS;
2424 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002425 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 pthread_mutex_lock(&out->lock);
2427 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2428 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2429 else
2430 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2431 pthread_mutex_unlock(&out->lock);
2432 }
2433 return status;
2434}
2435
2436static int out_flush(struct audio_stream_out* stream)
2437{
2438 struct stream_out *out = (struct stream_out *)stream;
2439 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002440 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002441 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 pthread_mutex_lock(&out->lock);
2443 stop_compressed_output_l(out);
2444 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002445 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002446 return 0;
2447 }
2448 return -ENOSYS;
2449}
2450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451/** audio_stream_in implementation **/
2452static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2453{
2454 struct stream_in *in = (struct stream_in *)stream;
2455
2456 return in->config.rate;
2457}
2458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002459static int in_set_sample_rate(struct audio_stream *stream __unused,
2460 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461{
2462 return -ENOSYS;
2463}
2464
2465static size_t in_get_buffer_size(const struct audio_stream *stream)
2466{
2467 struct stream_in *in = (struct stream_in *)stream;
2468
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002469 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2470 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002471 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2472 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002474 return in->config.period_size *
2475 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476}
2477
2478static uint32_t in_get_channels(const struct audio_stream *stream)
2479{
2480 struct stream_in *in = (struct stream_in *)stream;
2481
2482 return in->channel_mask;
2483}
2484
2485static audio_format_t in_get_format(const struct audio_stream *stream)
2486{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002487 struct stream_in *in = (struct stream_in *)stream;
2488
2489 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490}
2491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002492static int in_set_format(struct audio_stream *stream __unused,
2493 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494{
2495 return -ENOSYS;
2496}
2497
2498static int in_standby(struct audio_stream *stream)
2499{
2500 struct stream_in *in = (struct stream_in *)stream;
2501 struct audio_device *adev = in->dev;
2502 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302503 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2504 stream, in->usecase, use_case_table[in->usecase]);
2505
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002506 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2507 /* Ignore standby in case of voip call because the voip input
2508 * stream is closed in adev_close_input_stream()
2509 */
2510 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2511 return status;
2512 }
2513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002515 if (!in->standby && in->is_st_session) {
2516 ALOGD("%s: sound trigger pcm stop lab", __func__);
2517 audio_extn_sound_trigger_stop_lab(in);
2518 in->standby = 1;
2519 }
2520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002522 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002524 if (in->pcm) {
2525 pcm_close(in->pcm);
2526 in->pcm = NULL;
2527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002529 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 }
2531 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002532 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 return status;
2534}
2535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002536static int in_dump(const struct audio_stream *stream __unused,
2537 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538{
2539 return 0;
2540}
2541
2542static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2543{
2544 struct stream_in *in = (struct stream_in *)stream;
2545 struct audio_device *adev = in->dev;
2546 struct str_parms *parms;
2547 char *str;
2548 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002549 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302551 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 parms = str_parms_create_str(kvpairs);
2553
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302554 if (!parms)
2555 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002557 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002558
2559 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2560 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 val = atoi(value);
2562 /* no audio source uses val == 0 */
2563 if ((in->source != val) && (val != 0)) {
2564 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002565 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2566 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2567 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2568 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002569 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002570 err = voice_extn_compress_voip_open_input_stream(in);
2571 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002572 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002573 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002574 }
2575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 }
2577 }
2578
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002579 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2580 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002582 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 in->device = val;
2584 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002585 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002586 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588 }
2589
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002590done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002592 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
2594 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302595error:
Eric Laurent994a6932013-07-17 11:51:42 -07002596 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 return ret;
2598}
2599
2600static char* in_get_parameters(const struct audio_stream *stream,
2601 const char *keys)
2602{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002603 struct stream_in *in = (struct stream_in *)stream;
2604 struct str_parms *query = str_parms_create_str(keys);
2605 char *str;
2606 char value[256];
2607 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002608
2609 if (!query || !reply) {
2610 ALOGE("in_get_parameters: failed to create query or reply");
2611 return NULL;
2612 }
2613
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002614 ALOGV("%s: enter: keys - %s", __func__, keys);
2615
2616 voice_extn_in_get_parameters(in, query, reply);
2617
2618 str = str_parms_to_str(reply);
2619 str_parms_destroy(query);
2620 str_parms_destroy(reply);
2621
2622 ALOGV("%s: exit: returns - %s", __func__, str);
2623 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624}
2625
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002626static int in_set_gain(struct audio_stream_in *stream __unused,
2627 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628{
2629 return 0;
2630}
2631
2632static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2633 size_t bytes)
2634{
2635 struct stream_in *in = (struct stream_in *)stream;
2636 struct audio_device *adev = in->dev;
2637 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302638 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302641
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002642 if (in->is_st_session) {
2643 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2644 /* Read from sound trigger HAL */
2645 audio_extn_sound_trigger_read(in, buffer, bytes);
2646 pthread_mutex_unlock(&in->lock);
2647 return bytes;
2648 }
2649
2650 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2651 ALOGD(" %s: sound card is not active/SSR state", __func__);
2652 ret= -EIO;;
2653 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302654 }
2655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002657 pthread_mutex_lock(&adev->lock);
2658 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2659 ret = voice_extn_compress_voip_start_input_stream(in);
2660 else
2661 ret = start_input_stream(in);
2662 pthread_mutex_unlock(&adev->lock);
2663 if (ret != 0) {
2664 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 }
2666 in->standby = 0;
2667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668
2669 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002670 if (audio_extn_ssr_get_enabled() &&
2671 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002672 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002673 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2674 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002675 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2676 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002677 else
2678 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302679 if (ret < 0)
2680 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 }
2682
2683 /*
2684 * Instead of writing zeroes here, we could trust the hardware
2685 * to always provide zeroes when muted.
2686 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302687 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2688 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 memset(buffer, 0, bytes);
2690
2691exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302692 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302693 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002694 if (-ENETRESET == ret)
2695 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 pthread_mutex_unlock(&in->lock);
2698
2699 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302700 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302701 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302702 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302703 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302704 in->standby = true;
2705 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302706 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002708 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002709 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302710 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 }
2712 return bytes;
2713}
2714
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002715static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716{
2717 return 0;
2718}
2719
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002720static int add_remove_audio_effect(const struct audio_stream *stream,
2721 effect_handle_t effect,
2722 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724 struct stream_in *in = (struct stream_in *)stream;
2725 int status = 0;
2726 effect_descriptor_t desc;
2727
2728 status = (*effect)->get_descriptor(effect, &desc);
2729 if (status != 0)
2730 return status;
2731
2732 pthread_mutex_lock(&in->lock);
2733 pthread_mutex_lock(&in->dev->lock);
2734 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2735 in->enable_aec != enable &&
2736 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2737 in->enable_aec = enable;
2738 if (!in->standby)
2739 select_devices(in->dev, in->usecase);
2740 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002741 if (in->enable_ns != enable &&
2742 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2743 in->enable_ns = enable;
2744 if (!in->standby)
2745 select_devices(in->dev, in->usecase);
2746 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002747 pthread_mutex_unlock(&in->dev->lock);
2748 pthread_mutex_unlock(&in->lock);
2749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 return 0;
2751}
2752
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002753static int in_add_audio_effect(const struct audio_stream *stream,
2754 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
Eric Laurent994a6932013-07-17 11:51:42 -07002756 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002757 return add_remove_audio_effect(stream, effect, true);
2758}
2759
2760static int in_remove_audio_effect(const struct audio_stream *stream,
2761 effect_handle_t effect)
2762{
Eric Laurent994a6932013-07-17 11:51:42 -07002763 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002764 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765}
2766
2767static int adev_open_output_stream(struct audio_hw_device *dev,
2768 audio_io_handle_t handle,
2769 audio_devices_t devices,
2770 audio_output_flags_t flags,
2771 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002772 struct audio_stream_out **stream_out,
2773 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774{
2775 struct audio_device *adev = (struct audio_device *)dev;
2776 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002777 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002778 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302781
2782 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2783 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2784 ALOGE(" sound card is not active rejecting compress output open request");
2785 return -EINVAL;
2786 }
2787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2789
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302790 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2791 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2792 devices, flags, &out->stream);
2793
2794
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002795 if (!out) {
2796 return -ENOMEM;
2797 }
2798
Haynes Mathew George204045b2015-02-25 20:32:03 -08002799 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2800 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 if (devices == AUDIO_DEVICE_NONE)
2803 devices = AUDIO_DEVICE_OUT_SPEAKER;
2804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 out->flags = flags;
2806 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002807 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002808 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 out->sample_rate = config->sample_rate;
2810 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2811 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002812 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002813 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002814 out->non_blocking = 0;
2815 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816
2817 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002818 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2819 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002820 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2821 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2822
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002823 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002824 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2825 ret = read_hdmi_channel_masks(out);
2826
2827 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2828 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002829 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002830 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002831 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002832
2833 if (config->sample_rate == 0)
2834 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2835 if (config->channel_mask == 0)
2836 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2837
2838 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2841 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002843 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002845 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2846 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002847 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002848 ret = voice_extn_compress_voip_open_output_stream(out);
2849 if (ret != 0) {
2850 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2851 __func__, ret);
2852 goto error_open;
2853 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2855 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2856 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2857 ALOGE("%s: Unsupported Offload information", __func__);
2858 ret = -EINVAL;
2859 goto error_open;
2860 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002861
2862 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2863 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2864 ALOGV("read and update_pass through formats");
2865 ret = audio_extn_dolby_update_passt_formats(adev, out);
2866 if(ret != 0) {
2867 goto error_open;
2868 }
2869 if(config->offload_info.format == 0)
2870 config->offload_info.format = out->supported_formats[0];
2871 }
2872
Mingming Yin90310102013-11-13 16:57:00 -08002873 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002874 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 ALOGE("%s: Unsupported audio format", __func__);
2876 ret = -EINVAL;
2877 goto error_open;
2878 }
2879
2880 out->compr_config.codec = (struct snd_codec *)
2881 calloc(1, sizeof(struct snd_codec));
2882
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002883 if (!out->compr_config.codec) {
2884 ret = -ENOMEM;
2885 goto error_open;
2886 }
2887
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002888 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 if (config->offload_info.channel_mask)
2890 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002891 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002893 config->offload_info.channel_mask = config->channel_mask;
2894 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002895 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 out->sample_rate = config->offload_info.sample_rate;
2897
2898 out->stream.set_callback = out_set_callback;
2899 out->stream.pause = out_pause;
2900 out->stream.resume = out_resume;
2901 out->stream.drain = out_drain;
2902 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002903 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002905 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002906 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002907 audio_extn_dolby_get_snd_codec_id(adev, out,
2908 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002909 else
2910 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat2ec445f2015-07-23 18:02:31 +05302912 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002913 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002914 platform_get_pcm_offload_buffer_size(&config->offload_info);
2915 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2916 out->compr_config.fragment_size =
2917 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002918 } else {
2919 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002920 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002921 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2923 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002924 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 out->compr_config.codec->bit_rate =
2926 config->offload_info.bit_rate;
2927 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002928 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302930 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002931 /*TODO: Do we need to change it for passthrough */
2932 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933
Mingming Yin3ee55c62014-08-04 14:23:35 -07002934 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2935 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002936 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2937 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002938 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002939 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2940
Mingming Yin3ee55c62014-08-04 14:23:35 -07002941 if (out->bit_width == 24) {
2942 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2943 }
2944
Amit Shekhar6f461b12014-08-01 14:52:58 -07002945 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302946 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002947
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2949 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002950
Mingming Yin497419f2015-07-01 16:57:32 -07002951 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002952 //this flag is set from framework only if its for PCM formats
2953 //no need to check for PCM format again
2954 out->non_blocking = 0;
2955 out->use_small_bufs = true;
2956 ALOGI("Keep write blocking for small buff: non_blockling %d",
2957 out->non_blocking);
2958 }
2959
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002960 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002961 out->offload_state = OFFLOAD_STATE_IDLE;
2962 out->playback_started = 0;
2963
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002964 audio_extn_dts_create_state_notifier_node(out->usecase);
2965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966 create_offload_callback_thread(out);
2967 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2968 __func__, config->offload_info.version,
2969 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002970 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002971 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002972 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2973 ret = voice_check_and_set_incall_music_usecase(adev, out);
2974 if (ret != 0) {
2975 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2976 __func__, ret);
2977 goto error_open;
2978 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002979 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2980 if (config->sample_rate == 0)
2981 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2982 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2983 config->sample_rate != 8000) {
2984 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2985 ret = -EINVAL;
2986 goto error_open;
2987 }
2988 out->sample_rate = config->sample_rate;
2989 out->config.rate = config->sample_rate;
2990 if (config->format == AUDIO_FORMAT_DEFAULT)
2991 config->format = AUDIO_FORMAT_PCM_16_BIT;
2992 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2993 config->format = AUDIO_FORMAT_PCM_16_BIT;
2994 ret = -EINVAL;
2995 goto error_open;
2996 }
2997 out->format = config->format;
2998 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2999 out->config = pcm_config_afe_proxy_playback;
3000 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003001 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003002 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3004 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003005 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003006 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3007 format = AUDIO_FORMAT_PCM_16_BIT;
3008 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3009 out->config = pcm_config_deep_buffer;
3010 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003011 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003012 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003013 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003014 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003015 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003016 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 }
3018
Amit Shekhar1d896042014-10-03 13:16:09 -07003019 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3020 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003021 /* TODO remove this hardcoding and check why width is zero*/
3022 if (out->bit_width == 0)
3023 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003024 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3025 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003026 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003027 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003028 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3029 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3030 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003031 if(adev->primary_output == NULL)
3032 adev->primary_output = out;
3033 else {
3034 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003035 ret = -EEXIST;
3036 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003037 }
3038 }
3039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 /* Check if this usecase is already existing */
3041 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003042 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3043 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003046 ret = -EEXIST;
3047 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 }
3049 pthread_mutex_unlock(&adev->lock);
3050
3051 out->stream.common.get_sample_rate = out_get_sample_rate;
3052 out->stream.common.set_sample_rate = out_set_sample_rate;
3053 out->stream.common.get_buffer_size = out_get_buffer_size;
3054 out->stream.common.get_channels = out_get_channels;
3055 out->stream.common.get_format = out_get_format;
3056 out->stream.common.set_format = out_set_format;
3057 out->stream.common.standby = out_standby;
3058 out->stream.common.dump = out_dump;
3059 out->stream.common.set_parameters = out_set_parameters;
3060 out->stream.common.get_parameters = out_get_parameters;
3061 out->stream.common.add_audio_effect = out_add_audio_effect;
3062 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3063 out->stream.get_latency = out_get_latency;
3064 out->stream.set_volume = out_set_volume;
3065 out->stream.write = out_write;
3066 out->stream.get_render_position = out_get_render_position;
3067 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003068 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003071 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003072 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073
3074 config->format = out->stream.common.get_format(&out->stream.common);
3075 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3076 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3077
3078 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303079 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3080 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003081
3082 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3083 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3084 popcount(out->channel_mask), out->playback_started);
3085
Eric Laurent994a6932013-07-17 11:51:42 -07003086 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003088
3089error_open:
3090 free(out);
3091 *stream_out = NULL;
3092 ALOGD("%s: exit: ret %d", __func__, ret);
3093 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094}
3095
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003096static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 struct audio_stream_out *stream)
3098{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 struct stream_out *out = (struct stream_out *)stream;
3100 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003101 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303103 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3104
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003105 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303106 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003107 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303108 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003109 if(ret != 0)
3110 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3111 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003112 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003113 out_standby(&stream->common);
3114
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003115 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003116 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003118 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 if (out->compr_config.codec != NULL)
3120 free(out->compr_config.codec);
3121 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003122
3123 if (adev->voice_tx_output == out)
3124 adev->voice_tx_output = NULL;
3125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003126 pthread_cond_destroy(&out->cond);
3127 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003129 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130}
3131
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003132static void close_compress_sessions(struct audio_device *adev)
3133{
Mingming Yin7b762e72015-03-04 13:47:32 -08003134 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303135 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003136 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003137 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303138
3139 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003140 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303141 if (is_offload_usecase(usecase->id)) {
3142 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003143 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3144 out = usecase->stream.out;
3145 pthread_mutex_unlock(&adev->lock);
3146 out_standby(&out->stream.common);
3147 pthread_mutex_lock(&adev->lock);
3148 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303149 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003150 }
3151 pthread_mutex_unlock(&adev->lock);
3152}
3153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3155{
3156 struct audio_device *adev = (struct audio_device *)dev;
3157 struct str_parms *parms;
3158 char *str;
3159 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003160 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003161 int ret;
3162 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003164 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303167 if (!parms)
3168 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003169 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3170 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303172 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303173 struct listnode *node;
3174 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303175 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003177 //close compress sessions on OFFLINE status
3178 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303179 } else if (strstr(snd_card_status, "ONLINE")) {
3180 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303181 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003182 //send dts hpx license if enabled
3183 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303184 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303185 }
3186
3187 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003188 status = voice_set_parameters(adev, parms);
3189 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003190 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003192 status = platform_set_parameters(adev->platform, parms);
3193 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003194 goto done;
3195
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3197 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003198 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3200 adev->bluetooth_nrec = true;
3201 else
3202 adev->bluetooth_nrec = false;
3203 }
3204
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003205 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3206 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3208 adev->screen_off = false;
3209 else
3210 adev->screen_off = true;
3211 }
3212
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003213 ret = str_parms_get_int(parms, "rotation", &val);
3214 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003215 bool reverse_speakers = false;
3216 switch(val) {
3217 // FIXME: note that the code below assumes that the speakers are in the correct placement
3218 // relative to the user when the device is rotated 90deg from its default rotation. This
3219 // assumption is device-specific, not platform-specific like this code.
3220 case 270:
3221 reverse_speakers = true;
3222 break;
3223 case 0:
3224 case 90:
3225 case 180:
3226 break;
3227 default:
3228 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003229 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003230 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003231 if (status == 0) {
3232 if (adev->speaker_lr_swap != reverse_speakers) {
3233 adev->speaker_lr_swap = reverse_speakers;
3234 // only update the selected device if there is active pcm playback
3235 struct audio_usecase *usecase;
3236 struct listnode *node;
3237 list_for_each(node, &adev->usecase_list) {
3238 usecase = node_to_item(node, struct audio_usecase, list);
3239 if (usecase->type == PCM_PLAYBACK) {
3240 select_devices(adev, usecase->id);
3241 break;
3242 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003243 }
3244 }
3245 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003246 }
3247
Mingming Yin514a8bc2014-07-29 15:22:21 -07003248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3249 if (ret >= 0) {
3250 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3251 adev->bt_wb_speech_enabled = true;
3252 else
3253 adev->bt_wb_speech_enabled = false;
3254 }
3255
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003256 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3257 if (ret >= 0) {
3258 val = atoi(value);
3259 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3260 ALOGV("cache new edid");
3261 platform_cache_edid(adev->platform);
3262 }
3263 }
3264
3265 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3266 if (ret >= 0) {
3267 val = atoi(value);
3268 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3269 ALOGV("invalidate cached edid");
3270 platform_invalidate_edid(adev->platform);
3271 }
3272 }
3273
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003274 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003275
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003276done:
3277 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003278 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303279error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003280 ALOGV("%s: exit with code(%d)", __func__, status);
3281 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282}
3283
3284static char* adev_get_parameters(const struct audio_hw_device *dev,
3285 const char *keys)
3286{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003287 struct audio_device *adev = (struct audio_device *)dev;
3288 struct str_parms *reply = str_parms_create();
3289 struct str_parms *query = str_parms_create_str(keys);
3290 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303291 char value[256] = {0};
3292 int ret = 0;
3293
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003294 if (!query || !reply) {
3295 ALOGE("adev_get_parameters: failed to create query or reply");
3296 return NULL;
3297 }
3298
Naresh Tannirud7205b62014-06-20 02:54:48 +05303299 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3300 sizeof(value));
3301 if (ret >=0) {
3302 int val = 1;
3303 pthread_mutex_lock(&adev->snd_card_status.lock);
3304 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3305 val = 0;
3306 pthread_mutex_unlock(&adev->snd_card_status.lock);
3307 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3308 goto exit;
3309 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003310
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003311 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003312 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003313 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003314 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303315 pthread_mutex_unlock(&adev->lock);
3316
Naresh Tannirud7205b62014-06-20 02:54:48 +05303317exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003318 str = str_parms_to_str(reply);
3319 str_parms_destroy(query);
3320 str_parms_destroy(reply);
3321
3322 ALOGV("%s: exit: returns - %s", __func__, str);
3323 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327{
3328 return 0;
3329}
3330
3331static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3332{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003333 int ret;
3334 struct audio_device *adev = (struct audio_device *)dev;
3335 pthread_mutex_lock(&adev->lock);
3336 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003337 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003338 pthread_mutex_unlock(&adev->lock);
3339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340}
3341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003342static int adev_set_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_get_master_volume(struct audio_hw_device *dev __unused,
3349 float *volume __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_set_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
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003360static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3361 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 return -ENOSYS;
3364}
3365
3366static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3367{
3368 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 pthread_mutex_lock(&adev->lock);
3371 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003372 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003374 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3375 voice_is_in_call(adev)) {
3376 voice_stop_call(adev);
3377 adev->current_call_output = NULL;
3378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 }
3380 pthread_mutex_unlock(&adev->lock);
3381 return 0;
3382}
3383
3384static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3385{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003386 int ret;
3387
3388 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003389 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003390 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3391 pthread_mutex_unlock(&adev->lock);
3392
3393 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394}
3395
3396static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3397{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003398 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 return 0;
3400}
3401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003402static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 const struct audio_config *config)
3404{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003405 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003407 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3408 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409}
3410
3411static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003412 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 audio_devices_t devices,
3414 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003415 struct audio_stream_in **stream_in,
3416 audio_input_flags_t flags __unused,
3417 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003418 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419{
3420 struct audio_device *adev = (struct audio_device *)dev;
3421 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003422 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003423 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003424 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 *stream_in = NULL;
3427 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3428 return -EINVAL;
3429
3430 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003431
3432 if (!in) {
3433 ALOGE("failed to allocate input stream");
3434 return -ENOMEM;
3435 }
3436
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303437 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003438 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3439 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003441 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 in->stream.common.get_sample_rate = in_get_sample_rate;
3444 in->stream.common.set_sample_rate = in_set_sample_rate;
3445 in->stream.common.get_buffer_size = in_get_buffer_size;
3446 in->stream.common.get_channels = in_get_channels;
3447 in->stream.common.get_format = in_get_format;
3448 in->stream.common.set_format = in_set_format;
3449 in->stream.common.standby = in_standby;
3450 in->stream.common.dump = in_dump;
3451 in->stream.common.set_parameters = in_set_parameters;
3452 in->stream.common.get_parameters = in_get_parameters;
3453 in->stream.common.add_audio_effect = in_add_audio_effect;
3454 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3455 in->stream.set_gain = in_set_gain;
3456 in->stream.read = in_read;
3457 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3458
3459 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003460 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->standby = 1;
3463 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003464 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465
3466 /* Update config params with the requested sample rate and channels */
3467 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003468 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3469 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3470 is_low_latency = true;
3471#if LOW_LATENCY_CAPTURE_USE_CASE
3472 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3473#endif
3474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003477 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003479 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303480 if (adev->mode != AUDIO_MODE_IN_CALL) {
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003484 if (config->sample_rate == 0)
3485 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3486 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3487 config->sample_rate != 8000) {
3488 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3489 ret = -EINVAL;
3490 goto err_open;
3491 }
3492 if (config->format == AUDIO_FORMAT_DEFAULT)
3493 config->format = AUDIO_FORMAT_PCM_16_BIT;
3494 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3495 config->format = AUDIO_FORMAT_PCM_16_BIT;
3496 ret = -EINVAL;
3497 goto err_open;
3498 }
3499
3500 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3501 in->config = pcm_config_afe_proxy_record;
3502 in->config.channels = channel_count;
3503 in->config.rate = config->sample_rate;
3504 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003505 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003506 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003507 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3508 ret = -EINVAL;
3509 goto err_open;
3510 }
3511 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003512 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003513 }
Mingming Yine62d7842013-10-25 16:26:03 -07003514 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003515 audio_extn_compr_cap_format_supported(config->format) &&
3516 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003517 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 } else {
3519 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003520 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003521 buffer_size = get_input_buffer_size(config->sample_rate,
3522 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003523 channel_count,
3524 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003525 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003526 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3527 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3528 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3529 (in->config.rate == 8000 || in->config.rate == 16000) &&
3530 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3531 voice_extn_compress_voip_open_input_stream(in);
3532 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003535 /* This stream could be for sound trigger lab,
3536 get sound trigger pcm if present */
3537 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303538 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003541 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003542 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
3544err_open:
3545 free(in);
3546 *stream_in = NULL;
3547 return ret;
3548}
3549
3550static void adev_close_input_stream(struct audio_hw_device *dev,
3551 struct audio_stream_in *stream)
3552{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003553 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003554 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003555 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303556
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303557 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003558
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303559 /* Disable echo reference while closing input stream */
3560 platform_set_echo_reference(adev->platform, false);
3561
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003562 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303563 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003564 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303565 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003566 if (ret != 0)
3567 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3568 __func__, ret);
3569 } else
3570 in_standby(&stream->common);
3571
Mingming Yin7b762e72015-03-04 13:47:32 -08003572 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003574 audio_extn_ssr_deinit();
3575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
Mingming Yine62d7842013-10-25 16:26:03 -07003577 if(audio_extn_compr_cap_enabled() &&
3578 audio_extn_compr_cap_format_supported(in->config.format))
3579 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003580
3581 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 return;
3583}
3584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003585static int adev_dump(const audio_hw_device_t *device __unused,
3586 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 return 0;
3589}
3590
3591static int adev_close(hw_device_t *device)
3592{
3593 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003594
3595 if (!adev)
3596 return 0;
3597
3598 pthread_mutex_lock(&adev_init_lock);
3599
3600 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003601 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003602 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003603 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003604 audio_route_free(adev->audio_route);
3605 free(adev->snd_dev_ref_cnt);
3606 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003607 free(device);
3608 adev = NULL;
3609 }
3610 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 return 0;
3612}
3613
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003614/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3615 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3616 * just that it _might_ work.
3617 */
3618static int period_size_is_plausible_for_low_latency(int period_size)
3619{
3620 switch (period_size) {
3621 case 160:
3622 case 240:
3623 case 320:
3624 case 480:
3625 return 1;
3626 default:
3627 return 0;
3628 }
3629}
3630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631static int adev_open(const hw_module_t *module, const char *name,
3632 hw_device_t **device)
3633{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003634 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003636 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3638
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003639 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003640 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003641 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003642 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003643 ALOGD("%s: returning existing instance of adev", __func__);
3644 ALOGD("%s: exit", __func__);
3645 pthread_mutex_unlock(&adev_init_lock);
3646 return 0;
3647 }
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 adev = calloc(1, sizeof(struct audio_device));
3650
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003651 if (!adev) {
3652 pthread_mutex_unlock(&adev_init_lock);
3653 return -ENOMEM;
3654 }
3655
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003656 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3659 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3660 adev->device.common.module = (struct hw_module_t *)module;
3661 adev->device.common.close = adev_close;
3662
3663 adev->device.init_check = adev_init_check;
3664 adev->device.set_voice_volume = adev_set_voice_volume;
3665 adev->device.set_master_volume = adev_set_master_volume;
3666 adev->device.get_master_volume = adev_get_master_volume;
3667 adev->device.set_master_mute = adev_set_master_mute;
3668 adev->device.get_master_mute = adev_get_master_mute;
3669 adev->device.set_mode = adev_set_mode;
3670 adev->device.set_mic_mute = adev_set_mic_mute;
3671 adev->device.get_mic_mute = adev_get_mic_mute;
3672 adev->device.set_parameters = adev_set_parameters;
3673 adev->device.get_parameters = adev_get_parameters;
3674 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3675 adev->device.open_output_stream = adev_open_output_stream;
3676 adev->device.close_output_stream = adev_close_output_stream;
3677 adev->device.open_input_stream = adev_open_input_stream;
3678 adev->device.close_input_stream = adev_close_input_stream;
3679 adev->device.dump = adev_dump;
3680
3681 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003683 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003684 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003687 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003688 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003689 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003690 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003691 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003692 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003693 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303694
3695 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3696 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003698 adev->platform = platform_init(adev);
3699 if (!adev->platform) {
3700 free(adev->snd_dev_ref_cnt);
3701 free(adev);
3702 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3703 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003704 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003705 return -EINVAL;
3706 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003707
Naresh Tanniru4c630392014-05-12 01:05:52 +05303708 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3709
Eric Laurentc4aef752013-09-12 17:45:53 -07003710 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3711 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3712 if (adev->visualizer_lib == NULL) {
3713 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3714 } else {
3715 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3716 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003717 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003718 "visualizer_hal_start_output");
3719 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003720 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003721 "visualizer_hal_stop_output");
3722 }
3723 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003724 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003725 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003726
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003727 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3728 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3729 if (adev->offload_effects_lib == NULL) {
3730 ALOGE("%s: DLOPEN failed for %s", __func__,
3731 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3732 } else {
3733 ALOGV("%s: DLOPEN successful for %s", __func__,
3734 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3735 adev->offload_effects_start_output =
3736 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3737 "offload_effects_bundle_hal_start_output");
3738 adev->offload_effects_stop_output =
3739 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3740 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003741 adev->offload_effects_set_hpx_state =
3742 (int (*)(bool))dlsym(adev->offload_effects_lib,
3743 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003744 }
3745 }
3746
Mingming Yin514a8bc2014-07-29 15:22:21 -07003747 adev->bt_wb_speech_enabled = false;
3748
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003749 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 *device = &adev->device.common;
3751
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003752 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3753 &adev->streams_output_cfg_list);
3754
Kiran Kandi910e1862013-10-29 13:29:42 -07003755 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003756
3757 char value[PROPERTY_VALUE_MAX];
3758 int trial;
3759 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3760 trial = atoi(value);
3761 if (period_size_is_plausible_for_low_latency(trial)) {
3762 pcm_config_low_latency.period_size = trial;
3763 pcm_config_low_latency.start_threshold = trial / 4;
3764 pcm_config_low_latency.avail_min = trial / 4;
3765 configured_low_latency_capture_period_size = trial;
3766 }
3767 }
3768 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3769 trial = atoi(value);
3770 if (period_size_is_plausible_for_low_latency(trial)) {
3771 configured_low_latency_capture_period_size = trial;
3772 }
3773 }
3774
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003775 pthread_mutex_unlock(&adev_init_lock);
3776
Eric Laurent994a6932013-07-17 11:51:42 -07003777 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 return 0;
3779}
3780
3781static struct hw_module_methods_t hal_module_methods = {
3782 .open = adev_open,
3783};
3784
3785struct audio_module HAL_MODULE_INFO_SYM = {
3786 .common = {
3787 .tag = HARDWARE_MODULE_TAG,
3788 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3789 .hal_api_version = HARDWARE_HAL_API_VERSION,
3790 .id = AUDIO_HARDWARE_MODULE_ID,
3791 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003792 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 .methods = &hal_module_methods,
3794 },
3795};