blob: 303988fc18ae375844a0109d5e373bc4f6e559d6 [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) {
652 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
653 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);
684 /* Update the out_snd_device only before enabling the audio route */
685 if (switch_device[usecase->id] ) {
686 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800687 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530688 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 }
690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 }
692}
693
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700694static void check_and_route_capture_usecases(struct audio_device *adev,
695 struct audio_usecase *uc_info,
696 snd_device_t snd_device)
697{
698 struct listnode *node;
699 struct audio_usecase *usecase;
700 bool switch_device[AUDIO_USECASE_MAX];
701 int i, num_uc_to_switch = 0;
702
703 /*
704 * This function is to make sure that all the active capture usecases
705 * are always routed to the same input sound device.
706 * For example, if audio-record and voice-call usecases are currently
707 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
708 * is received for voice call then we have to make sure that audio-record
709 * usecase is also switched to earpiece i.e. voice-dmic-ef,
710 * because of the limitation that two devices cannot be enabled
711 * at the same time if they share the same backend.
712 */
713 for (i = 0; i < AUDIO_USECASE_MAX; i++)
714 switch_device[i] = false;
715
716 list_for_each(node, &adev->usecase_list) {
717 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800718 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700720 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700721 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
722 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700723 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
725 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700726 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 switch_device[usecase->id] = true;
729 num_uc_to_switch++;
730 }
731 }
732
733 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700734 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530736 /* Make sure the previous devices to be disabled first and then enable the
737 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
740 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700741 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800742 }
743 }
744
745 list_for_each(node, &adev->usecase_list) {
746 usecase = node_to_item(node, struct audio_usecase, list);
747 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700748 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749 }
750 }
751
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700752 /* Re-route all the usecases on the shared backend other than the
753 specified usecase to new snd devices */
754 list_for_each(node, &adev->usecase_list) {
755 usecase = node_to_item(node, struct audio_usecase, list);
756 /* Update the in_snd_device only before enabling the audio route */
757 if (switch_device[usecase->id] ) {
758 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800759 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530760 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700761 }
762 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 }
764}
765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700767static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700769 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700770 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771
772 switch (channels) {
773 /*
774 * Do not handle stereo output in Multi-channel cases
775 * Stereo case is handled in normal playback path
776 */
777 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700778 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784 break;
785 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700786 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 break;
794 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700795 ALOGE("HDMI does not support multi channel playback");
796 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 break;
798 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700799 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800800}
801
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800802audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
803 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700804{
805 struct audio_usecase *usecase;
806 struct listnode *node;
807
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800810 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700811 ALOGV("%s: usecase id %d", __func__, usecase->id);
812 return usecase->id;
813 }
814 }
815 return USECASE_INVALID;
816}
817
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700818struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700819 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820{
821 struct audio_usecase *usecase;
822 struct listnode *node;
823
824 list_for_each(node, &adev->usecase_list) {
825 usecase = node_to_item(node, struct audio_usecase, list);
826 if (usecase->id == uc_id)
827 return usecase;
828 }
829 return NULL;
830}
831
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700832int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800834 snd_device_t out_snd_device = SND_DEVICE_NONE;
835 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 struct audio_usecase *usecase = NULL;
837 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800838 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800839 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800840 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800841 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 usecase = get_usecase_from_list(adev, uc_id);
845 if (usecase == NULL) {
846 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
847 return -EINVAL;
848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800849
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800850 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800851 (usecase->type == VOIP_CALL) ||
852 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700853 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800854 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700855 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 usecase->devices = usecase->stream.out->devices;
857 } else {
858 /*
859 * If the voice call is active, use the sound devices of voice call usecase
860 * so that it would not result any device switch. All the usecases will
861 * be switched to new device when select_devices() is called for voice call
862 * usecase. This is to avoid switching devices for voice call when
863 * check_usecases_codec_backend() is called below.
864 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700865 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700866 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800867 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
869 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 in_snd_device = vc_usecase->in_snd_device;
871 out_snd_device = vc_usecase->out_snd_device;
872 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800873 } else if (voice_extn_compress_voip_is_active(adev)) {
874 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700875 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530876 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700877 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800878 in_snd_device = voip_usecase->in_snd_device;
879 out_snd_device = voip_usecase->out_snd_device;
880 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800881 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800882 hfp_ucid = audio_extn_hfp_get_usecase();
883 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700884 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800885 in_snd_device = hfp_usecase->in_snd_device;
886 out_snd_device = hfp_usecase->out_snd_device;
887 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 }
889 if (usecase->type == PCM_PLAYBACK) {
890 usecase->devices = usecase->stream.out->devices;
891 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700892 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700893 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800894 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700895 if (usecase->stream.out == adev->primary_output &&
896 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800897 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
898 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700899 select_devices(adev, adev->active_input->usecase);
900 }
901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 } else if (usecase->type == PCM_CAPTURE) {
903 usecase->devices = usecase->stream.in->device;
904 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700905 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700906 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530907 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
908 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
909 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
910 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800912 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700913 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
914 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700916 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700917 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 }
919 }
920
921 if (out_snd_device == usecase->out_snd_device &&
922 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923 return 0;
924 }
925
sangwoobc677242013-08-08 16:53:43 +0900926 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700927 out_snd_device, platform_get_snd_device_name(out_snd_device),
928 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800930 /*
931 * Limitation: While in call, to do a device switch we need to disable
932 * and enable both RX and TX devices though one of them is same as current
933 * device.
934 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700935 if ((usecase->type == VOICE_CALL) &&
936 (usecase->in_snd_device != SND_DEVICE_NONE) &&
937 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700938 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700939 /* Disable sidetone only if voice call already exists */
940 if (voice_is_call_state_active(adev))
941 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800942 }
943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 /* Disable current sound devices */
945 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700946 disable_audio_route(adev, usecase);
947 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 }
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700951 disable_audio_route(adev, usecase);
952 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953 }
954
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800955 /* Applicable only on the targets that has external modem.
956 * New device information should be sent to modem before enabling
957 * the devices to reduce in-call device switch time.
958 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700959 if ((usecase->type == VOICE_CALL) &&
960 (usecase->in_snd_device != SND_DEVICE_NONE) &&
961 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800962 status = platform_switch_voice_call_enable_device_config(adev->platform,
963 out_snd_device,
964 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700965 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800966
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967 /* Enable new sound devices */
968 if (out_snd_device != SND_DEVICE_NONE) {
969 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
970 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700971 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 }
973
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 if (in_snd_device != SND_DEVICE_NONE) {
975 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700976 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700977 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978
Avinash Vaish71a8b972014-07-24 15:36:33 +0530979 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700980 status = platform_switch_voice_call_device_post(adev->platform,
981 out_snd_device,
982 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530983 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700984 /* Enable sidetone only if voice call already exists */
985 if (voice_is_call_state_active(adev))
986 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530987 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800988
sangwoo170731f2013-06-08 15:36:36 +0900989 usecase->in_snd_device = in_snd_device;
990 usecase->out_snd_device = out_snd_device;
991
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530992 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700993 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530994 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700995 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530996 usecase->stream.out->flags,
997 usecase->stream.out->format,
998 usecase->stream.out->sample_rate,
999 usecase->stream.out->bit_width,
1000 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001001 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301002 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001003
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001004 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001005
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001006 /* Applicable only on the targets that has external modem.
1007 * Enable device command should be sent to modem only after
1008 * enabling voice call mixer controls
1009 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001010 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001011 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1012 out_snd_device,
1013 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301014 ALOGD("%s: done",__func__);
1015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016 return status;
1017}
1018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019static int stop_input_stream(struct stream_in *in)
1020{
1021 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 struct audio_usecase *uc_info;
1023 struct audio_device *adev = in->dev;
1024
Eric Laurentc8400632013-02-14 19:04:54 -08001025 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026
Eric Laurent994a6932013-07-17 11:51:42 -07001027 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001028 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 uc_info = get_usecase_from_list(adev, in->usecase);
1030 if (uc_info == NULL) {
1031 ALOGE("%s: Could not find the usecase (%d) in the list",
1032 __func__, in->usecase);
1033 return -EINVAL;
1034 }
1035
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001036 /* Close in-call recording streams */
1037 voice_check_and_stop_incall_rec_usecase(adev, in);
1038
Eric Laurent150dbfe2013-02-27 14:31:02 -08001039 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001040 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041
1042 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001043 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001045 list_remove(&uc_info->list);
1046 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Eric Laurent994a6932013-07-17 11:51:42 -07001048 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049 return ret;
1050}
1051
1052int start_input_stream(struct stream_in *in)
1053{
1054 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001055 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056 struct audio_usecase *uc_info;
1057 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301058 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059
Mingming Yine62d7842013-10-25 16:26:03 -07001060 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301061 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1062 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001063
Naresh Tanniru80659832014-06-04 18:17:56 +05301064
1065 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301066 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301067 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301068 goto error_config;
1069 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301070
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001071 /* Check if source matches incall recording usecase criteria */
1072 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1073 if (ret)
1074 goto error_config;
1075 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001076 ALOGD("%s: Updated usecase(%d: %s)",
1077 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001078
Eric Laurentb23d5282013-05-14 15:27:20 -07001079 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080 if (in->pcm_device_id < 0) {
1081 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1082 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001083 ret = -EINVAL;
1084 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086
1087 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001089
1090 if (!uc_info) {
1091 ret = -ENOMEM;
1092 goto error_config;
1093 }
1094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 uc_info->id = in->usecase;
1096 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001097 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 uc_info->devices = in->device;
1099 uc_info->in_snd_device = SND_DEVICE_NONE;
1100 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001102 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301103 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105
Eric Laurentc8400632013-02-14 19:04:54 -08001106 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001107 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1108
1109 unsigned int flags = PCM_IN;
1110 unsigned int pcm_open_retry_count = 0;
1111
1112 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1113 flags |= PCM_MMAP | PCM_NOIRQ;
1114 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1115 }
1116
1117 while (1) {
1118 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1119 flags, &in->config);
1120 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1121 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1122 if (in->pcm != NULL) {
1123 pcm_close(in->pcm);
1124 in->pcm = NULL;
1125 }
1126 if (pcm_open_retry_count-- == 0) {
1127 ret = -EIO;
1128 goto error_open;
1129 }
1130 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1131 continue;
1132 }
1133 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301135 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301136
Eric Laurent994a6932013-07-17 11:51:42 -07001137 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001138 return ret;
1139
1140error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301142 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001143
1144error_config:
1145 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001147
1148 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149}
1150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001151/* must be called with out->lock locked */
1152static int send_offload_cmd_l(struct stream_out* out, int command)
1153{
1154 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1155
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001156 if (!cmd) {
1157 ALOGE("failed to allocate mem for command 0x%x", command);
1158 return -ENOMEM;
1159 }
1160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001161 ALOGVV("%s %d", __func__, command);
1162
1163 cmd->cmd = command;
1164 list_add_tail(&out->offload_cmd_list, &cmd->node);
1165 pthread_cond_signal(&out->offload_cond);
1166 return 0;
1167}
1168
1169/* must be called iwth out->lock locked */
1170static void stop_compressed_output_l(struct stream_out *out)
1171{
1172 out->offload_state = OFFLOAD_STATE_IDLE;
1173 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001174 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001175 if (out->compr != NULL) {
1176 compress_stop(out->compr);
1177 while (out->offload_thread_blocked) {
1178 pthread_cond_wait(&out->cond, &out->lock);
1179 }
1180 }
1181}
1182
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001183bool is_offload_usecase(audio_usecase_t uc_id)
1184{
1185 unsigned int i;
1186 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1187 if (uc_id == offload_usecases[i])
1188 return true;
1189 }
1190 return false;
1191}
1192
1193static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1194{
1195 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1196 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1197 char value[PROPERTY_VALUE_MAX] = {0};
1198
1199 property_get("audio.offload.multiple.enabled", value, NULL);
1200 if (!(atoi(value) || !strncmp("true", value, 4)))
1201 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1202
1203 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1204 for (i = 0; i < num_usecase; i++) {
1205 if (!(adev->offload_usecases_state & (0x1<<i))) {
1206 adev->offload_usecases_state |= 0x1 << i;
1207 ret = offload_usecases[i];
1208 break;
1209 }
1210 }
1211 ALOGV("%s: offload usecase is %d", __func__, ret);
1212 return ret;
1213}
1214
1215static void free_offload_usecase(struct audio_device *adev,
1216 audio_usecase_t uc_id)
1217{
1218 unsigned int i;
1219 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1220 if (offload_usecases[i] == uc_id) {
1221 adev->offload_usecases_state &= ~(0x1<<i);
1222 break;
1223 }
1224 }
1225 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1226}
1227
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001228static void *offload_thread_loop(void *context)
1229{
1230 struct stream_out *out = (struct stream_out *) context;
1231 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001232 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001234 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1235 set_sched_policy(0, SP_FOREGROUND);
1236 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1237
1238 ALOGV("%s", __func__);
1239 pthread_mutex_lock(&out->lock);
1240 for (;;) {
1241 struct offload_cmd *cmd = NULL;
1242 stream_callback_event_t event;
1243 bool send_callback = false;
1244
1245 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1246 __func__, list_empty(&out->offload_cmd_list),
1247 out->offload_state);
1248 if (list_empty(&out->offload_cmd_list)) {
1249 ALOGV("%s SLEEPING", __func__);
1250 pthread_cond_wait(&out->offload_cond, &out->lock);
1251 ALOGV("%s RUNNING", __func__);
1252 continue;
1253 }
1254
1255 item = list_head(&out->offload_cmd_list);
1256 cmd = node_to_item(item, struct offload_cmd, node);
1257 list_remove(item);
1258
1259 ALOGVV("%s STATE %d CMD %d out->compr %p",
1260 __func__, out->offload_state, cmd->cmd, out->compr);
1261
1262 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1263 free(cmd);
1264 break;
1265 }
1266
1267 if (out->compr == NULL) {
1268 ALOGE("%s: Compress handle is NULL", __func__);
1269 pthread_cond_signal(&out->cond);
1270 continue;
1271 }
1272 out->offload_thread_blocked = true;
1273 pthread_mutex_unlock(&out->lock);
1274 send_callback = false;
1275 switch(cmd->cmd) {
1276 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001277 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001278 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001279 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001280 send_callback = true;
1281 event = STREAM_CBK_EVENT_WRITE_READY;
1282 break;
1283 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001284 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301285 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001286 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301287 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301289 if (ret < 0)
1290 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301291 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301292 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001293 compress_drain(out->compr);
1294 else
1295 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301296 if (ret != -ENETRESET) {
1297 send_callback = true;
1298 event = STREAM_CBK_EVENT_DRAIN_READY;
1299 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1300 } else
1301 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001302 break;
1303 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001304 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001306 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 send_callback = true;
1308 event = STREAM_CBK_EVENT_DRAIN_READY;
1309 break;
1310 default:
1311 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1312 break;
1313 }
1314 pthread_mutex_lock(&out->lock);
1315 out->offload_thread_blocked = false;
1316 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001317 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001318 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001320 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001321 free(cmd);
1322 }
1323
1324 pthread_cond_signal(&out->cond);
1325 while (!list_empty(&out->offload_cmd_list)) {
1326 item = list_head(&out->offload_cmd_list);
1327 list_remove(item);
1328 free(node_to_item(item, struct offload_cmd, node));
1329 }
1330 pthread_mutex_unlock(&out->lock);
1331
1332 return NULL;
1333}
1334
1335static int create_offload_callback_thread(struct stream_out *out)
1336{
1337 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1338 list_init(&out->offload_cmd_list);
1339 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1340 offload_thread_loop, out);
1341 return 0;
1342}
1343
1344static int destroy_offload_callback_thread(struct stream_out *out)
1345{
1346 pthread_mutex_lock(&out->lock);
1347 stop_compressed_output_l(out);
1348 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1349
1350 pthread_mutex_unlock(&out->lock);
1351 pthread_join(out->offload_thread, (void **) NULL);
1352 pthread_cond_destroy(&out->offload_cond);
1353
1354 return 0;
1355}
1356
Eric Laurent07eeafd2013-10-06 12:52:49 -07001357static bool allow_hdmi_channel_config(struct audio_device *adev)
1358{
1359 struct listnode *node;
1360 struct audio_usecase *usecase;
1361 bool ret = true;
1362
1363 list_for_each(node, &adev->usecase_list) {
1364 usecase = node_to_item(node, struct audio_usecase, list);
1365 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1366 /*
1367 * If voice call is already existing, do not proceed further to avoid
1368 * disabling/enabling both RX and TX devices, CSD calls, etc.
1369 * Once the voice call done, the HDMI channels can be configured to
1370 * max channels of remaining use cases.
1371 */
1372 if (usecase->id == USECASE_VOICE_CALL) {
1373 ALOGD("%s: voice call is active, no change in HDMI channels",
1374 __func__);
1375 ret = false;
1376 break;
1377 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1378 ALOGD("%s: multi channel playback is active, "
1379 "no change in HDMI channels", __func__);
1380 ret = false;
1381 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001382 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001383 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001384 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1385 ", no change in HDMI channels", __func__,
1386 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001387 ret = false;
1388 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 }
1390 }
1391 }
1392 return ret;
1393}
1394
1395static int check_and_set_hdmi_channels(struct audio_device *adev,
1396 unsigned int channels)
1397{
1398 struct listnode *node;
1399 struct audio_usecase *usecase;
1400
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001401 unsigned int supported_channels = platform_edid_get_max_channels(
1402 adev->platform);
1403 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001404 /* Check if change in HDMI channel config is allowed */
1405 if (!allow_hdmi_channel_config(adev))
1406 return 0;
1407
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001408 if (channels > supported_channels)
1409 channels = supported_channels;
1410
Eric Laurent07eeafd2013-10-06 12:52:49 -07001411 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001412 ALOGD("%s: Requested channels are same as current channels(%d)",
1413 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 return 0;
1415 }
1416
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001417 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001418 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001419 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 adev->cur_hdmi_channels = channels;
1421
1422 /*
1423 * Deroute all the playback streams routed to HDMI so that
1424 * the back end is deactivated. Note that backend will not
1425 * be deactivated if any one stream is connected to it.
1426 */
1427 list_for_each(node, &adev->usecase_list) {
1428 usecase = node_to_item(node, struct audio_usecase, list);
1429 if (usecase->type == PCM_PLAYBACK &&
1430 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001431 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432 }
1433 }
1434
1435 /*
1436 * Enable all the streams disabled above. Now the HDMI backend
1437 * will be activated with new channel configuration
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 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001444 }
1445 }
1446
1447 return 0;
1448}
1449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450static int stop_output_stream(struct stream_out *out)
1451{
1452 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 struct audio_usecase *uc_info;
1454 struct audio_device *adev = out->dev;
1455
Eric Laurent994a6932013-07-17 11:51:42 -07001456 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 uc_info = get_usecase_from_list(adev, out->usecase);
1459 if (uc_info == NULL) {
1460 ALOGE("%s: Could not find the usecase (%d) in the list",
1461 __func__, out->usecase);
1462 return -EINVAL;
1463 }
1464
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001465 if (is_offload_usecase(out->usecase) &&
1466 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001467 if (adev->visualizer_stop_output != NULL)
1468 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001469
1470 audio_extn_dts_remove_state_notifier_node(out->usecase);
1471
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001472 if (adev->offload_effects_stop_output != NULL)
1473 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1474 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001475
Eric Laurent150dbfe2013-02-27 14:31:02 -08001476 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478
1479 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001480 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001482 list_remove(&uc_info->list);
1483 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001485 if (is_offload_usecase(out->usecase) &&
1486 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1487 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1488 ALOGV("Disable passthrough , reset mixer to pcm");
1489 /* NO_PASSTHROUGH */
1490 out->compr_config.codec->compr_passthr = 0;
1491 audio_extn_dolby_set_hdmi_config(adev, out);
1492 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1493 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001494 /* Must be called after removing the usecase from list */
1495 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1496 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1497
Eric Laurent994a6932013-07-17 11:51:42 -07001498 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 return ret;
1500}
1501
1502int start_output_stream(struct stream_out *out)
1503{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001505 int sink_channels = 0;
1506 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 struct audio_usecase *uc_info;
1508 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301509 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001511 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1512 ret = -EINVAL;
1513 goto error_config;
1514 }
1515
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301516 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1517 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1518 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301519
Naresh Tanniru80659832014-06-04 18:17:56 +05301520 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301521 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301522 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301523 goto error_config;
1524 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301525
Eric Laurentb23d5282013-05-14 15:27:20 -07001526 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527 if (out->pcm_device_id < 0) {
1528 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1529 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001530 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001531 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 }
1533
1534 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001535
1536 if (!uc_info) {
1537 ret = -ENOMEM;
1538 goto error_config;
1539 }
1540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 uc_info->id = out->usecase;
1542 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001543 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 uc_info->devices = out->devices;
1545 uc_info->in_snd_device = SND_DEVICE_NONE;
1546 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001547 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001548 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001549 if (is_offload_usecase(out->usecase)) {
1550 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001551 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1552 }
1553 }
Mingming Yin9c041392014-05-01 15:37:31 -07001554 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1555 if (!strncmp("true", prop_value, 4)) {
1556 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001557 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1558 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001559 check_and_set_hdmi_channels(adev, sink_channels);
1560 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001561 if (is_offload_usecase(out->usecase)) {
1562 unsigned int ch_count = out->compr_config.codec->ch_in;
1563 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1564 /* backend channel config for passthrough stream is stereo */
1565 ch_count = 2;
1566 check_and_set_hdmi_channels(adev, ch_count);
1567 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001568 check_and_set_hdmi_channels(adev, out->config.channels);
1569 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001570 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001571 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001572 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574 select_devices(adev, out->usecase);
1575
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001576 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1577 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001578 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001579 unsigned int flags = PCM_OUT;
1580 unsigned int pcm_open_retry_count = 0;
1581 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1582 flags |= PCM_MMAP | PCM_NOIRQ;
1583 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1584 } else
1585 flags |= PCM_MONOTONIC;
1586
1587 while (1) {
1588 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1589 flags, &out->config);
1590 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1591 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1592 if (out->pcm != NULL) {
1593 pcm_close(out->pcm);
1594 out->pcm = NULL;
1595 }
1596 if (pcm_open_retry_count-- == 0) {
1597 ret = -EIO;
1598 goto error_open;
1599 }
1600 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1601 continue;
1602 }
1603 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001604 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001605 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1606 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001608 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1609 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001611 out->compr = compress_open(adev->snd_card,
1612 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001613 COMPRESS_IN, &out->compr_config);
1614 if (out->compr && !is_compress_ready(out->compr)) {
1615 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1616 compress_close(out->compr);
1617 out->compr = NULL;
1618 ret = -EIO;
1619 goto error_open;
1620 }
1621 if (out->offload_callback)
1622 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001623
Fred Oh3f43e742015-03-04 18:42:34 -08001624 /* Since small bufs uses blocking writes, a write will be blocked
1625 for the default max poll time (20s) in the event of an SSR.
1626 Reduce the poll time to observe and deal with SSR faster.
1627 */
1628 if (out->use_small_bufs) {
1629 compress_set_max_poll_wait(out->compr, 1000);
1630 }
1631
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001632 audio_extn_dts_create_state_notifier_node(out->usecase);
1633 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1634 popcount(out->channel_mask),
1635 out->playback_started);
1636
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001637#ifdef DS1_DOLBY_DDP_ENABLED
1638 if (audio_extn_is_dolby_format(out->format))
1639 audio_extn_dolby_send_ddp_endp_params(adev);
1640#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001641 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1642 if (adev->visualizer_start_output != NULL)
1643 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1644 if (adev->offload_effects_start_output != NULL)
1645 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001646 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 }
Eric Laurent994a6932013-07-17 11:51:42 -07001649 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001651error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001653error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001654 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655}
1656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657static int check_input_parameters(uint32_t sample_rate,
1658 audio_format_t format,
1659 int channel_count)
1660{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001661 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001663 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001664 !voice_extn_compress_voip_is_format_supported(format) &&
1665 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001666
1667 switch (channel_count) {
1668 case 1:
1669 case 2:
1670 case 6:
1671 break;
1672 default:
1673 ret = -EINVAL;
1674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675
1676 switch (sample_rate) {
1677 case 8000:
1678 case 11025:
1679 case 12000:
1680 case 16000:
1681 case 22050:
1682 case 24000:
1683 case 32000:
1684 case 44100:
1685 case 48000:
1686 break;
1687 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001688 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 }
1690
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692}
1693
1694static size_t get_input_buffer_size(uint32_t sample_rate,
1695 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001696 int channel_count,
1697 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698{
1699 size_t size = 0;
1700
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001701 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1702 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001704 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001705 if (is_low_latency)
1706 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001707 /* ToDo: should use frame_size computed based on the format and
1708 channel_count here. */
1709 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001711 /* make sure the size is multiple of 32 bytes
1712 * At 48 kHz mono 16-bit PCM:
1713 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1714 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1715 */
1716 size += 0x1f;
1717 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001718
1719 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720}
1721
1722static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1723{
1724 struct stream_out *out = (struct stream_out *)stream;
1725
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727}
1728
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001729static int out_set_sample_rate(struct audio_stream *stream __unused,
1730 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731{
1732 return -ENOSYS;
1733}
1734
1735static size_t out_get_buffer_size(const struct audio_stream *stream)
1736{
1737 struct stream_out *out = (struct stream_out *)stream;
1738
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001739 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001741 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1742 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001743
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001744 return out->config.period_size *
1745 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746}
1747
1748static uint32_t out_get_channels(const struct audio_stream *stream)
1749{
1750 struct stream_out *out = (struct stream_out *)stream;
1751
1752 return out->channel_mask;
1753}
1754
1755static audio_format_t out_get_format(const struct audio_stream *stream)
1756{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 struct stream_out *out = (struct stream_out *)stream;
1758
1759 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760}
1761
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001762static int out_set_format(struct audio_stream *stream __unused,
1763 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764{
1765 return -ENOSYS;
1766}
1767
1768static int out_standby(struct audio_stream *stream)
1769{
1770 struct stream_out *out = (struct stream_out *)stream;
1771 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301773 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1774 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001775 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1776 /* Ignore standby in case of voip call because the voip output
1777 * stream is closed in adev_close_output_stream()
1778 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301779 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001780 return 0;
1781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001783 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001785 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001787 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 if (out->pcm) {
1789 pcm_close(out->pcm);
1790 out->pcm = NULL;
1791 }
1792 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001793 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001795 out->gapless_mdata.encoder_delay = 0;
1796 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001797 if (out->compr != NULL) {
1798 compress_close(out->compr);
1799 out->compr = NULL;
1800 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001803 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 }
1805 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001806 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 return 0;
1808}
1809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001810static int out_dump(const struct audio_stream *stream __unused,
1811 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812{
1813 return 0;
1814}
1815
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001816static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1817{
1818 int ret = 0;
1819 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001821
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001823 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001824 return -EINVAL;
1825 }
1826
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001827 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1828 if (ret >= 0) {
1829 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1830 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1831 ALOGV("ADTS format is set in offload mode");
1832 }
1833 out->send_new_metadata = 1;
1834 }
1835
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301836 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001837
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001838 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1839 if(ret >= 0)
1840 is_meta_data_params = true;
1841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301842 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001843 is_meta_data_params = true;
1844 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301845 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001846 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001847 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1848 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001849 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301850 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001852 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1853 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001854 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301855 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001856 }
1857
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001858 if(!is_meta_data_params) {
1859 ALOGV("%s: Not gapless meta data params", __func__);
1860 return 0;
1861 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 out->send_new_metadata = 1;
1863 ALOGV("%s new encoder delay %u and padding %u", __func__,
1864 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1865
1866 return 0;
1867}
1868
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001869static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1870{
1871 return out == adev->primary_output || out == adev->voice_tx_output;
1872}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1875{
1876 struct stream_out *out = (struct stream_out *)stream;
1877 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001878 struct audio_usecase *usecase;
1879 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 struct str_parms *parms;
1881 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001882 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001883 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884
sangwoobc677242013-08-08 16:53:43 +09001885 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301888 if (!parms)
1889 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001890 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1891 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001894 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301897 * When HDMI cable is unplugged/usb hs is disconnected the
1898 * music playback is paused and the policy manager sends routing=0
1899 * But the audioflingercontinues to write data until standby time
1900 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 * Avoid this by routing audio to speaker until standby.
1902 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301903 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1904 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001906 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1907 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908 }
1909
1910 /*
1911 * select_devices() call below switches all the usecases on the same
1912 * backend to the new device. Refer to check_usecases_codec_backend() in
1913 * the select_devices(). But how do we undo this?
1914 *
1915 * For example, music playback is active on headset (deep-buffer usecase)
1916 * and if we go to ringtones and select a ringtone, low-latency usecase
1917 * will be started on headset+speaker. As we can't enable headset+speaker
1918 * and headset devices at the same time, select_devices() switches the music
1919 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1920 * So when the ringtone playback is completed, how do we undo the same?
1921 *
1922 * We are relying on the out_set_parameters() call on deep-buffer output,
1923 * once the ringtone playback is ended.
1924 * NOTE: We should not check if the current devices are same as new devices.
1925 * Because select_devices() must be called to switch back the music
1926 * playback to headset.
1927 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001928 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001929 out->devices = val;
1930
1931 if (!out->standby)
1932 select_devices(adev, out->usecase);
1933
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001934 if (output_drives_call(adev, out)) {
1935 if(!voice_is_in_call(adev)) {
1936 if (adev->mode == AUDIO_MODE_IN_CALL) {
1937 adev->current_call_output = out;
1938 ret = voice_start_call(adev);
1939 }
1940 } else {
1941 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001942 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001943 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001944 }
1945 }
1946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001948 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001950
1951 if (out == adev->primary_output) {
1952 pthread_mutex_lock(&adev->lock);
1953 audio_extn_set_parameters(adev, parms);
1954 pthread_mutex_unlock(&adev->lock);
1955 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001956 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001957 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001958 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001959
1960 audio_extn_dts_create_state_notifier_node(out->usecase);
1961 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1962 popcount(out->channel_mask),
1963 out->playback_started);
1964
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001965 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001966 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301969error:
Eric Laurent994a6932013-07-17 11:51:42 -07001970 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 return ret;
1972}
1973
1974static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1975{
1976 struct stream_out *out = (struct stream_out *)stream;
1977 struct str_parms *query = str_parms_create_str(keys);
1978 char *str;
1979 char value[256];
1980 struct str_parms *reply = str_parms_create();
1981 size_t i, j;
1982 int ret;
1983 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001984
1985 if (!query || !reply) {
1986 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1987 return NULL;
1988 }
1989
Eric Laurent994a6932013-07-17 11:51:42 -07001990 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1992 if (ret >= 0) {
1993 value[0] = '\0';
1994 i = 0;
1995 while (out->supported_channel_masks[i] != 0) {
1996 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1997 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1998 if (!first) {
1999 strcat(value, "|");
2000 }
2001 strcat(value, out_channels_name_to_enum_table[j].name);
2002 first = false;
2003 break;
2004 }
2005 }
2006 i++;
2007 }
2008 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2009 str = str_parms_to_str(reply);
2010 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002011 voice_extn_out_get_parameters(out, query, reply);
2012 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002013 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002014 free(str);
2015 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002018
2019 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2020 if (ret >= 0) {
2021 value[0] = '\0';
2022 i = 0;
2023 first = true;
2024 while (out->supported_formats[i] != 0) {
2025 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2026 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2027 if (!first) {
2028 strcat(value, "|");
2029 }
2030 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2031 first = false;
2032 break;
2033 }
2034 }
2035 i++;
2036 }
2037 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2038 str = str_parms_to_str(reply);
2039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 str_parms_destroy(query);
2041 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002042 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 return str;
2044}
2045
2046static uint32_t out_get_latency(const struct audio_stream_out *stream)
2047{
2048 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002049 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Alexy Josephaa54c872014-12-03 02:46:47 -08002051 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002052 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002053 } else {
2054 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002056 }
2057
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302058 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002059 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static int out_set_volume(struct audio_stream_out *stream, float left,
2063 float right)
2064{
Eric Laurenta9024de2013-04-04 09:19:12 -07002065 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 int volume[2];
2067
Eric Laurenta9024de2013-04-04 09:19:12 -07002068 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2069 /* only take left channel into account: the API is for stereo anyway */
2070 out->muted = (left == 0.0f);
2071 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002072 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002073 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2074 /*
2075 * Set mute or umute on HDMI passthrough stream.
2076 * Only take left channel into account.
2077 * Mute is 0 and unmute 1
2078 */
2079 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2080 } else {
2081 char mixer_ctl_name[128];
2082 struct audio_device *adev = out->dev;
2083 struct mixer_ctl *ctl;
2084 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002085 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002087 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2088 "Compress Playback %d Volume", pcm_device_id);
2089 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2090 if (!ctl) {
2091 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2092 __func__, mixer_ctl_name);
2093 return -EINVAL;
2094 }
2095 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2096 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2097 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2098 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002100 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 return -ENOSYS;
2103}
2104
2105static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2106 size_t bytes)
2107{
2108 struct stream_out *out = (struct stream_out *)stream;
2109 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302110 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002111 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302114
Naresh Tanniru80659832014-06-04 18:17:56 +05302115 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002116 // increase written size during SSR to avoid mismatch
2117 // with the written frames count in AF
2118 if (!is_offload_usecase(out->usecase))
2119 out->written += bytes / (out->config.channels * sizeof(short));
2120
Naresh Tanniru80659832014-06-04 18:17:56 +05302121 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302122 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302123 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302124 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002125 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 //during SSR for compress usecase we should return error to flinger
2127 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2128 pthread_mutex_unlock(&out->lock);
2129 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302130 }
2131 }
2132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002134 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002136 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2137 ret = voice_extn_compress_voip_start_output_stream(out);
2138 else
2139 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002140 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002143 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 goto exit;
2145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002148 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002149 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002151 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2153 out->send_new_metadata = 0;
2154 }
2155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302157 if (ret < 0)
2158 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002159 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002160 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302161 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302163 } else if (-ENETRESET == ret) {
2164 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2166 pthread_mutex_unlock(&out->lock);
2167 out_standby(&out->stream.common);
2168 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302170 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002172 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 out->playback_started = 1;
2174 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002175
2176 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2177 popcount(out->channel_mask),
2178 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 }
2180 pthread_mutex_unlock(&out->lock);
2181 return ret;
2182 } else {
2183 if (out->pcm) {
2184 if (out->muted)
2185 memset((void *)buffer, 0, bytes);
2186 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002187 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2188 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2189 else
2190 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302191 if (ret < 0)
2192 ret = -errno;
2193 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002194 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 }
2197
2198exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302199 /* ToDo: There may be a corner case when SSR happens back to back during
2200 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302201 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302202 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302203 }
2204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 pthread_mutex_unlock(&out->lock);
2206
2207 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002208 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002209 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302210 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302211 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302212 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302213 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302214 out->standby = true;
2215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002217 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302218 out_get_sample_rate(&out->stream.common));
2219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 }
2221 return bytes;
2222}
2223
2224static int out_get_render_position(const struct audio_stream_out *stream,
2225 uint32_t *dsp_frames)
2226{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002227 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302228 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002229
2230 if (dsp_frames == NULL)
2231 return -EINVAL;
2232
2233 *dsp_frames = 0;
2234 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002235 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 pthread_mutex_lock(&out->lock);
2237 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302238 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302240 if (ret < 0)
2241 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 ALOGVV("%s rendered frames %d sample_rate %d",
2243 __func__, *dsp_frames, out->sample_rate);
2244 }
2245 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302246 if (-ENETRESET == ret) {
2247 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2248 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2249 return -EINVAL;
2250 } else if(ret < 0) {
2251 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2252 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302253 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2254 /*
2255 * Handle corner case where compress session is closed during SSR
2256 * and timestamp is queried
2257 */
2258 ALOGE(" ERROR: sound card not active, return error");
2259 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302260 } else {
2261 return 0;
2262 }
Zhou Song32a556e2015-05-05 10:46:56 +08002263 } else if (audio_is_linear_pcm(out->format)) {
2264 *dsp_frames = out->written;
2265 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 } else
2267 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268}
2269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002270static int out_add_audio_effect(const struct audio_stream *stream __unused,
2271 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272{
2273 return 0;
2274}
2275
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002276static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2277 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278{
2279 return 0;
2280}
2281
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002282static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2283 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284{
2285 return -EINVAL;
2286}
2287
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002288static int out_get_presentation_position(const struct audio_stream_out *stream,
2289 uint64_t *frames, struct timespec *timestamp)
2290{
2291 struct stream_out *out = (struct stream_out *)stream;
2292 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002293 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002294
2295 pthread_mutex_lock(&out->lock);
2296
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002297 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002298 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302299 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002300 &out->sample_rate);
2301 ALOGVV("%s rendered frames %ld sample_rate %d",
2302 __func__, dsp_frames, out->sample_rate);
2303 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302304 if (ret < 0)
2305 ret = -errno;
2306 if (-ENETRESET == ret) {
2307 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2308 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2309 ret = -EINVAL;
2310 } else
2311 ret = 0;
2312
Eric Laurent949a0892013-09-20 09:20:13 -07002313 /* this is the best we can do */
2314 clock_gettime(CLOCK_MONOTONIC, timestamp);
2315 }
2316 } else {
2317 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002318 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002319 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2320 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002321 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002322 // This adjustment accounts for buffering after app processor.
2323 // It is based on estimated DSP latency per use case, rather than exact.
2324 signed_frames -=
2325 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2326
Eric Laurent949a0892013-09-20 09:20:13 -07002327 // It would be unusual for this value to be negative, but check just in case ...
2328 if (signed_frames >= 0) {
2329 *frames = signed_frames;
2330 ret = 0;
2331 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002332 }
2333 }
2334 }
2335
2336 pthread_mutex_unlock(&out->lock);
2337
2338 return ret;
2339}
2340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341static int out_set_callback(struct audio_stream_out *stream,
2342 stream_callback_t callback, void *cookie)
2343{
2344 struct stream_out *out = (struct stream_out *)stream;
2345
2346 ALOGV("%s", __func__);
2347 pthread_mutex_lock(&out->lock);
2348 out->offload_callback = callback;
2349 out->offload_cookie = cookie;
2350 pthread_mutex_unlock(&out->lock);
2351 return 0;
2352}
2353
2354static int out_pause(struct audio_stream_out* stream)
2355{
2356 struct stream_out *out = (struct stream_out *)stream;
2357 int status = -ENOSYS;
2358 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002359 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002360 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 pthread_mutex_lock(&out->lock);
2362 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302363 struct audio_device *adev = out->dev;
2364 int snd_scard_state = get_snd_card_state(adev);
2365
2366 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2367 status = compress_pause(out->compr);
2368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002370
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302371 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372 audio_extn_dts_notify_playback_state(out->usecase, 0,
2373 out->sample_rate, popcount(out->channel_mask),
2374 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 }
2376 pthread_mutex_unlock(&out->lock);
2377 }
2378 return status;
2379}
2380
2381static int out_resume(struct audio_stream_out* stream)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384 int status = -ENOSYS;
2385 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002386 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002387 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 status = 0;
2389 pthread_mutex_lock(&out->lock);
2390 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302391 struct audio_device *adev = out->dev;
2392 int snd_scard_state = get_snd_card_state(adev);
2393
2394 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2395 status = compress_resume(out->compr);
2396
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002398
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302399 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002400 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2401 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 }
2403 pthread_mutex_unlock(&out->lock);
2404 }
2405 return status;
2406}
2407
2408static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2409{
2410 struct stream_out *out = (struct stream_out *)stream;
2411 int status = -ENOSYS;
2412 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002413 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 pthread_mutex_lock(&out->lock);
2415 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2416 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2417 else
2418 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2419 pthread_mutex_unlock(&out->lock);
2420 }
2421 return status;
2422}
2423
2424static int out_flush(struct audio_stream_out* stream)
2425{
2426 struct stream_out *out = (struct stream_out *)stream;
2427 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002428 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002429 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 pthread_mutex_lock(&out->lock);
2431 stop_compressed_output_l(out);
2432 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002433 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 return 0;
2435 }
2436 return -ENOSYS;
2437}
2438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439/** audio_stream_in implementation **/
2440static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2441{
2442 struct stream_in *in = (struct stream_in *)stream;
2443
2444 return in->config.rate;
2445}
2446
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002447static int in_set_sample_rate(struct audio_stream *stream __unused,
2448 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449{
2450 return -ENOSYS;
2451}
2452
2453static size_t in_get_buffer_size(const struct audio_stream *stream)
2454{
2455 struct stream_in *in = (struct stream_in *)stream;
2456
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002457 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2458 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002459 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2460 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002461
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002462 return in->config.period_size *
2463 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464}
2465
2466static uint32_t in_get_channels(const struct audio_stream *stream)
2467{
2468 struct stream_in *in = (struct stream_in *)stream;
2469
2470 return in->channel_mask;
2471}
2472
2473static audio_format_t in_get_format(const struct audio_stream *stream)
2474{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002475 struct stream_in *in = (struct stream_in *)stream;
2476
2477 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002480static int in_set_format(struct audio_stream *stream __unused,
2481 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482{
2483 return -ENOSYS;
2484}
2485
2486static int in_standby(struct audio_stream *stream)
2487{
2488 struct stream_in *in = (struct stream_in *)stream;
2489 struct audio_device *adev = in->dev;
2490 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302491 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2492 stream, in->usecase, use_case_table[in->usecase]);
2493
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002494 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2495 /* Ignore standby in case of voip call because the voip input
2496 * stream is closed in adev_close_input_stream()
2497 */
2498 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2499 return status;
2500 }
2501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002503 if (!in->standby && in->is_st_session) {
2504 ALOGD("%s: sound trigger pcm stop lab", __func__);
2505 audio_extn_sound_trigger_stop_lab(in);
2506 in->standby = 1;
2507 }
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002510 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002512 if (in->pcm) {
2513 pcm_close(in->pcm);
2514 in->pcm = NULL;
2515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002517 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 }
2519 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002520 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 return status;
2522}
2523
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002524static int in_dump(const struct audio_stream *stream __unused,
2525 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526{
2527 return 0;
2528}
2529
2530static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2531{
2532 struct stream_in *in = (struct stream_in *)stream;
2533 struct audio_device *adev = in->dev;
2534 struct str_parms *parms;
2535 char *str;
2536 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002537 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302539 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 parms = str_parms_create_str(kvpairs);
2541
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302542 if (!parms)
2543 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002546
2547 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2548 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 val = atoi(value);
2550 /* no audio source uses val == 0 */
2551 if ((in->source != val) && (val != 0)) {
2552 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002553 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2554 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2555 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2556 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002557 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002558 err = voice_extn_compress_voip_open_input_stream(in);
2559 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002560 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002561 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002562 }
2563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 }
2565 }
2566
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002567 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2568 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002570 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 in->device = val;
2572 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002573 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 }
2576 }
2577
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002578done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002580 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
2582 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302583error:
Eric Laurent994a6932013-07-17 11:51:42 -07002584 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 return ret;
2586}
2587
2588static char* in_get_parameters(const struct audio_stream *stream,
2589 const char *keys)
2590{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002591 struct stream_in *in = (struct stream_in *)stream;
2592 struct str_parms *query = str_parms_create_str(keys);
2593 char *str;
2594 char value[256];
2595 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002596
2597 if (!query || !reply) {
2598 ALOGE("in_get_parameters: failed to create query or reply");
2599 return NULL;
2600 }
2601
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002602 ALOGV("%s: enter: keys - %s", __func__, keys);
2603
2604 voice_extn_in_get_parameters(in, query, reply);
2605
2606 str = str_parms_to_str(reply);
2607 str_parms_destroy(query);
2608 str_parms_destroy(reply);
2609
2610 ALOGV("%s: exit: returns - %s", __func__, str);
2611 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002614static int in_set_gain(struct audio_stream_in *stream __unused,
2615 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616{
2617 return 0;
2618}
2619
2620static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2621 size_t bytes)
2622{
2623 struct stream_in *in = (struct stream_in *)stream;
2624 struct audio_device *adev = in->dev;
2625 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302626 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302629
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002630 if (in->is_st_session) {
2631 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2632 /* Read from sound trigger HAL */
2633 audio_extn_sound_trigger_read(in, buffer, bytes);
2634 pthread_mutex_unlock(&in->lock);
2635 return bytes;
2636 }
2637
2638 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2639 ALOGD(" %s: sound card is not active/SSR state", __func__);
2640 ret= -EIO;;
2641 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302642 }
2643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002645 pthread_mutex_lock(&adev->lock);
2646 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2647 ret = voice_extn_compress_voip_start_input_stream(in);
2648 else
2649 ret = start_input_stream(in);
2650 pthread_mutex_unlock(&adev->lock);
2651 if (ret != 0) {
2652 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 }
2654 in->standby = 0;
2655 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656
2657 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002658 if (audio_extn_ssr_get_enabled() &&
2659 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002660 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002661 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2662 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002663 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2664 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002665 else
2666 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302667 if (ret < 0)
2668 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 }
2670
2671 /*
2672 * Instead of writing zeroes here, we could trust the hardware
2673 * to always provide zeroes when muted.
2674 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302675 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2676 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 memset(buffer, 0, bytes);
2678
2679exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302680 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302681 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002682 if (-ENETRESET == ret)
2683 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 pthread_mutex_unlock(&in->lock);
2686
2687 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302688 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302689 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302690 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302691 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302692 in->standby = true;
2693 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302694 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002696 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002697 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302698 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
2700 return bytes;
2701}
2702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002703static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
2705 return 0;
2706}
2707
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002708static int add_remove_audio_effect(const struct audio_stream *stream,
2709 effect_handle_t effect,
2710 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712 struct stream_in *in = (struct stream_in *)stream;
2713 int status = 0;
2714 effect_descriptor_t desc;
2715
2716 status = (*effect)->get_descriptor(effect, &desc);
2717 if (status != 0)
2718 return status;
2719
2720 pthread_mutex_lock(&in->lock);
2721 pthread_mutex_lock(&in->dev->lock);
2722 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2723 in->enable_aec != enable &&
2724 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2725 in->enable_aec = enable;
2726 if (!in->standby)
2727 select_devices(in->dev, in->usecase);
2728 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002729 if (in->enable_ns != enable &&
2730 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2731 in->enable_ns = enable;
2732 if (!in->standby)
2733 select_devices(in->dev, in->usecase);
2734 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002735 pthread_mutex_unlock(&in->dev->lock);
2736 pthread_mutex_unlock(&in->lock);
2737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 return 0;
2739}
2740
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002741static int in_add_audio_effect(const struct audio_stream *stream,
2742 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743{
Eric Laurent994a6932013-07-17 11:51:42 -07002744 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002745 return add_remove_audio_effect(stream, effect, true);
2746}
2747
2748static int in_remove_audio_effect(const struct audio_stream *stream,
2749 effect_handle_t effect)
2750{
Eric Laurent994a6932013-07-17 11:51:42 -07002751 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002752 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753}
2754
2755static int adev_open_output_stream(struct audio_hw_device *dev,
2756 audio_io_handle_t handle,
2757 audio_devices_t devices,
2758 audio_output_flags_t flags,
2759 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002760 struct audio_stream_out **stream_out,
2761 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762{
2763 struct audio_device *adev = (struct audio_device *)dev;
2764 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002765 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002766 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302769
2770 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2771 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2772 ALOGE(" sound card is not active rejecting compress output open request");
2773 return -EINVAL;
2774 }
2775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2777
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302778 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2779 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2780 devices, flags, &out->stream);
2781
2782
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002783 if (!out) {
2784 return -ENOMEM;
2785 }
2786
Haynes Mathew George204045b2015-02-25 20:32:03 -08002787 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2788 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 if (devices == AUDIO_DEVICE_NONE)
2791 devices = AUDIO_DEVICE_OUT_SPEAKER;
2792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 out->flags = flags;
2794 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002795 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002796 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002797 out->sample_rate = config->sample_rate;
2798 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2799 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002800 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002801 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002802 out->non_blocking = 0;
2803 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804
2805 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002806 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2807 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2808 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2809
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002810 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002811 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2812 ret = read_hdmi_channel_masks(out);
2813
2814 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2815 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002816 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002817 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002818 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002819
2820 if (config->sample_rate == 0)
2821 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2822 if (config->channel_mask == 0)
2823 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2824
2825 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2828 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002830 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002832 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2833 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002834 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002835 ret = voice_extn_compress_voip_open_output_stream(out);
2836 if (ret != 0) {
2837 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2838 __func__, ret);
2839 goto error_open;
2840 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2842 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2843 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2844 ALOGE("%s: Unsupported Offload information", __func__);
2845 ret = -EINVAL;
2846 goto error_open;
2847 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002848
2849 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2850 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2851 ALOGV("read and update_pass through formats");
2852 ret = audio_extn_dolby_update_passt_formats(adev, out);
2853 if(ret != 0) {
2854 goto error_open;
2855 }
2856 if(config->offload_info.format == 0)
2857 config->offload_info.format = out->supported_formats[0];
2858 }
2859
Mingming Yin90310102013-11-13 16:57:00 -08002860 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002861 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 ALOGE("%s: Unsupported audio format", __func__);
2863 ret = -EINVAL;
2864 goto error_open;
2865 }
2866
2867 out->compr_config.codec = (struct snd_codec *)
2868 calloc(1, sizeof(struct snd_codec));
2869
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002870 if (!out->compr_config.codec) {
2871 ret = -ENOMEM;
2872 goto error_open;
2873 }
2874
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002875 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 if (config->offload_info.channel_mask)
2877 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002878 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002880 config->offload_info.channel_mask = config->channel_mask;
2881 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002882 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 out->sample_rate = config->offload_info.sample_rate;
2884
2885 out->stream.set_callback = out_set_callback;
2886 out->stream.pause = out_pause;
2887 out->stream.resume = out_resume;
2888 out->stream.drain = out_drain;
2889 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002890 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002892 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002893 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002894 audio_extn_dolby_get_snd_codec_id(adev, out,
2895 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002896 else
2897 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 if (audio_is_offload_pcm(config->offload_info.format)) {
2900 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002901 platform_get_pcm_offload_buffer_size(&config->offload_info);
2902 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2903 out->compr_config.fragment_size =
2904 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002905 } else {
2906 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002907 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002908 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2910 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002911 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 out->compr_config.codec->bit_rate =
2913 config->offload_info.bit_rate;
2914 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002915 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002918 /*TODO: Do we need to change it for passthrough */
2919 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920
Mingming Yin3ee55c62014-08-04 14:23:35 -07002921 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2922 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002923 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2924 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002925 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002926 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2927
Mingming Yin3ee55c62014-08-04 14:23:35 -07002928 if (out->bit_width == 24) {
2929 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2930 }
2931
Amit Shekhar6f461b12014-08-01 14:52:58 -07002932 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002933 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2936 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002937
Mingming Yin497419f2015-07-01 16:57:32 -07002938 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002939 //this flag is set from framework only if its for PCM formats
2940 //no need to check for PCM format again
2941 out->non_blocking = 0;
2942 out->use_small_bufs = true;
2943 ALOGI("Keep write blocking for small buff: non_blockling %d",
2944 out->non_blocking);
2945 }
2946
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002947 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002948 out->offload_state = OFFLOAD_STATE_IDLE;
2949 out->playback_started = 0;
2950
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002951 audio_extn_dts_create_state_notifier_node(out->usecase);
2952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 create_offload_callback_thread(out);
2954 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2955 __func__, config->offload_info.version,
2956 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002957 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002958 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002959 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2960 ret = voice_check_and_set_incall_music_usecase(adev, out);
2961 if (ret != 0) {
2962 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2963 __func__, ret);
2964 goto error_open;
2965 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002966 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2967 if (config->sample_rate == 0)
2968 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2969 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2970 config->sample_rate != 8000) {
2971 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2972 ret = -EINVAL;
2973 goto error_open;
2974 }
2975 out->sample_rate = config->sample_rate;
2976 out->config.rate = config->sample_rate;
2977 if (config->format == AUDIO_FORMAT_DEFAULT)
2978 config->format = AUDIO_FORMAT_PCM_16_BIT;
2979 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2980 config->format = AUDIO_FORMAT_PCM_16_BIT;
2981 ret = -EINVAL;
2982 goto error_open;
2983 }
2984 out->format = config->format;
2985 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2986 out->config = pcm_config_afe_proxy_playback;
2987 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002988 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002989 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2991 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002993 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2994 format = AUDIO_FORMAT_PCM_16_BIT;
2995 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2996 out->config = pcm_config_deep_buffer;
2997 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002998 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002999 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003000 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003001 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003002 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003003 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 }
3005
Amit Shekhar1d896042014-10-03 13:16:09 -07003006 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3007 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003008 /* TODO remove this hardcoding and check why width is zero*/
3009 if (out->bit_width == 0)
3010 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003011 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3012 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003013 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003014 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003015 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3016 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3017 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003018 if(adev->primary_output == NULL)
3019 adev->primary_output = out;
3020 else {
3021 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003022 ret = -EEXIST;
3023 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003024 }
3025 }
3026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 /* Check if this usecase is already existing */
3028 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003029 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3030 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003033 ret = -EEXIST;
3034 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 }
3036 pthread_mutex_unlock(&adev->lock);
3037
3038 out->stream.common.get_sample_rate = out_get_sample_rate;
3039 out->stream.common.set_sample_rate = out_set_sample_rate;
3040 out->stream.common.get_buffer_size = out_get_buffer_size;
3041 out->stream.common.get_channels = out_get_channels;
3042 out->stream.common.get_format = out_get_format;
3043 out->stream.common.set_format = out_set_format;
3044 out->stream.common.standby = out_standby;
3045 out->stream.common.dump = out_dump;
3046 out->stream.common.set_parameters = out_set_parameters;
3047 out->stream.common.get_parameters = out_get_parameters;
3048 out->stream.common.add_audio_effect = out_add_audio_effect;
3049 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3050 out->stream.get_latency = out_get_latency;
3051 out->stream.set_volume = out_set_volume;
3052 out->stream.write = out_write;
3053 out->stream.get_render_position = out_get_render_position;
3054 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003055 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003058 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003059 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060
3061 config->format = out->stream.common.get_format(&out->stream.common);
3062 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3063 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3064
3065 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303066 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3067 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003068
3069 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3070 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3071 popcount(out->channel_mask), out->playback_started);
3072
Eric Laurent994a6932013-07-17 11:51:42 -07003073 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003075
3076error_open:
3077 free(out);
3078 *stream_out = NULL;
3079 ALOGD("%s: exit: ret %d", __func__, ret);
3080 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081}
3082
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003083static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 struct audio_stream_out *stream)
3085{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 struct stream_out *out = (struct stream_out *)stream;
3087 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003088 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303090 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3091
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003092 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303093 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003094 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303095 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003096 if(ret != 0)
3097 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3098 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003099 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003100 out_standby(&stream->common);
3101
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003102 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003103 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003105 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 if (out->compr_config.codec != NULL)
3107 free(out->compr_config.codec);
3108 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109
3110 if (adev->voice_tx_output == out)
3111 adev->voice_tx_output = NULL;
3112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003113 pthread_cond_destroy(&out->cond);
3114 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003116 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117}
3118
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003119static void close_compress_sessions(struct audio_device *adev)
3120{
Mingming Yin7b762e72015-03-04 13:47:32 -08003121 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303122 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003123 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003124 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303125
3126 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003127 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303128 if (is_offload_usecase(usecase->id)) {
3129 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3131 out = usecase->stream.out;
3132 pthread_mutex_unlock(&adev->lock);
3133 out_standby(&out->stream.common);
3134 pthread_mutex_lock(&adev->lock);
3135 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303136 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003137 }
3138 pthread_mutex_unlock(&adev->lock);
3139}
3140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3142{
3143 struct audio_device *adev = (struct audio_device *)dev;
3144 struct str_parms *parms;
3145 char *str;
3146 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003147 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003148 int ret;
3149 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003151 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303154 if (!parms)
3155 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003156 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3157 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303159 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303160 struct listnode *node;
3161 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303163 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003164 //close compress sessions on OFFLINE status
3165 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303166 } else if (strstr(snd_card_status, "ONLINE")) {
3167 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303168 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003169 //send dts hpx license if enabled
3170 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303172 }
3173
3174 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003175 status = voice_set_parameters(adev, parms);
3176 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003177 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 status = platform_set_parameters(adev->platform, parms);
3180 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003181 goto done;
3182
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003183 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3184 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003185 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3187 adev->bluetooth_nrec = true;
3188 else
3189 adev->bluetooth_nrec = false;
3190 }
3191
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003192 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3193 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3195 adev->screen_off = false;
3196 else
3197 adev->screen_off = true;
3198 }
3199
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003200 ret = str_parms_get_int(parms, "rotation", &val);
3201 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003202 bool reverse_speakers = false;
3203 switch(val) {
3204 // FIXME: note that the code below assumes that the speakers are in the correct placement
3205 // relative to the user when the device is rotated 90deg from its default rotation. This
3206 // assumption is device-specific, not platform-specific like this code.
3207 case 270:
3208 reverse_speakers = true;
3209 break;
3210 case 0:
3211 case 90:
3212 case 180:
3213 break;
3214 default:
3215 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003216 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003217 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003218 if (status == 0) {
3219 if (adev->speaker_lr_swap != reverse_speakers) {
3220 adev->speaker_lr_swap = reverse_speakers;
3221 // only update the selected device if there is active pcm playback
3222 struct audio_usecase *usecase;
3223 struct listnode *node;
3224 list_for_each(node, &adev->usecase_list) {
3225 usecase = node_to_item(node, struct audio_usecase, list);
3226 if (usecase->type == PCM_PLAYBACK) {
3227 select_devices(adev, usecase->id);
3228 break;
3229 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003230 }
3231 }
3232 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003233 }
3234
Mingming Yin514a8bc2014-07-29 15:22:21 -07003235 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3236 if (ret >= 0) {
3237 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3238 adev->bt_wb_speech_enabled = true;
3239 else
3240 adev->bt_wb_speech_enabled = false;
3241 }
3242
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003243 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3244 if (ret >= 0) {
3245 val = atoi(value);
3246 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3247 ALOGV("cache new edid");
3248 platform_cache_edid(adev->platform);
3249 }
3250 }
3251
3252 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3253 if (ret >= 0) {
3254 val = atoi(value);
3255 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3256 ALOGV("invalidate cached edid");
3257 platform_invalidate_edid(adev->platform);
3258 }
3259 }
3260
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003261 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003262
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003263done:
3264 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003265 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303266error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003267 ALOGV("%s: exit with code(%d)", __func__, status);
3268 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269}
3270
3271static char* adev_get_parameters(const struct audio_hw_device *dev,
3272 const char *keys)
3273{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003274 struct audio_device *adev = (struct audio_device *)dev;
3275 struct str_parms *reply = str_parms_create();
3276 struct str_parms *query = str_parms_create_str(keys);
3277 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303278 char value[256] = {0};
3279 int ret = 0;
3280
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003281 if (!query || !reply) {
3282 ALOGE("adev_get_parameters: failed to create query or reply");
3283 return NULL;
3284 }
3285
Naresh Tannirud7205b62014-06-20 02:54:48 +05303286 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3287 sizeof(value));
3288 if (ret >=0) {
3289 int val = 1;
3290 pthread_mutex_lock(&adev->snd_card_status.lock);
3291 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3292 val = 0;
3293 pthread_mutex_unlock(&adev->snd_card_status.lock);
3294 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3295 goto exit;
3296 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003297
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003298 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003299 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003300 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003301 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303302 pthread_mutex_unlock(&adev->lock);
3303
Naresh Tannirud7205b62014-06-20 02:54:48 +05303304exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003305 str = str_parms_to_str(reply);
3306 str_parms_destroy(query);
3307 str_parms_destroy(reply);
3308
3309 ALOGV("%s: exit: returns - %s", __func__, str);
3310 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003313static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314{
3315 return 0;
3316}
3317
3318static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3319{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003320 int ret;
3321 struct audio_device *adev = (struct audio_device *)dev;
3322 pthread_mutex_lock(&adev->lock);
3323 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003324 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003325 pthread_mutex_unlock(&adev->lock);
3326 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327}
3328
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003329static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3330 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331{
3332 return -ENOSYS;
3333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3336 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return -ENOSYS;
3339}
3340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003341static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3342 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return -ENOSYS;
3345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3348 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return -ENOSYS;
3351}
3352
3353static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3354{
3355 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 pthread_mutex_lock(&adev->lock);
3358 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003359 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003361 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3362 voice_is_in_call(adev)) {
3363 voice_stop_call(adev);
3364 adev->current_call_output = NULL;
3365 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 }
3367 pthread_mutex_unlock(&adev->lock);
3368 return 0;
3369}
3370
3371static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3372{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003373 int ret;
3374
3375 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003376 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003377 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3378 pthread_mutex_unlock(&adev->lock);
3379
3380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
3383static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3384{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003385 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 return 0;
3387}
3388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 const struct audio_config *config)
3391{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003392 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003394 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3395 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
3398static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003399 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 audio_devices_t devices,
3401 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003402 struct audio_stream_in **stream_in,
3403 audio_input_flags_t flags __unused,
3404 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003405 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406{
3407 struct audio_device *adev = (struct audio_device *)dev;
3408 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003409 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003410 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003411 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 *stream_in = NULL;
3414 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3415 return -EINVAL;
3416
3417 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003418
3419 if (!in) {
3420 ALOGE("failed to allocate input stream");
3421 return -ENOMEM;
3422 }
3423
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303424 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003425 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3426 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003428 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 in->stream.common.get_sample_rate = in_get_sample_rate;
3431 in->stream.common.set_sample_rate = in_set_sample_rate;
3432 in->stream.common.get_buffer_size = in_get_buffer_size;
3433 in->stream.common.get_channels = in_get_channels;
3434 in->stream.common.get_format = in_get_format;
3435 in->stream.common.set_format = in_set_format;
3436 in->stream.common.standby = in_standby;
3437 in->stream.common.dump = in_dump;
3438 in->stream.common.set_parameters = in_set_parameters;
3439 in->stream.common.get_parameters = in_get_parameters;
3440 in->stream.common.add_audio_effect = in_add_audio_effect;
3441 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3442 in->stream.set_gain = in_set_gain;
3443 in->stream.read = in_read;
3444 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3445
3446 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003447 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 in->standby = 1;
3450 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003451 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452
3453 /* Update config params with the requested sample rate and channels */
3454 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003455 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3456 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3457 is_low_latency = true;
3458#if LOW_LATENCY_CAPTURE_USE_CASE
3459 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3460#endif
3461 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003464 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003466 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303467 if (adev->mode != AUDIO_MODE_IN_CALL) {
3468 ret = -EINVAL;
3469 goto err_open;
3470 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003471 if (config->sample_rate == 0)
3472 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3473 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3474 config->sample_rate != 8000) {
3475 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3476 ret = -EINVAL;
3477 goto err_open;
3478 }
3479 if (config->format == AUDIO_FORMAT_DEFAULT)
3480 config->format = AUDIO_FORMAT_PCM_16_BIT;
3481 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3482 config->format = AUDIO_FORMAT_PCM_16_BIT;
3483 ret = -EINVAL;
3484 goto err_open;
3485 }
3486
3487 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3488 in->config = pcm_config_afe_proxy_record;
3489 in->config.channels = channel_count;
3490 in->config.rate = config->sample_rate;
3491 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003492 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003493 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003494 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3495 ret = -EINVAL;
3496 goto err_open;
3497 }
3498 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003499 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003500 }
Mingming Yine62d7842013-10-25 16:26:03 -07003501 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003502 audio_extn_compr_cap_format_supported(config->format) &&
3503 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003504 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003505 } else {
3506 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003507 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 buffer_size = get_input_buffer_size(config->sample_rate,
3509 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003510 channel_count,
3511 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003512 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003513 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3514 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3515 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3516 (in->config.rate == 8000 || in->config.rate == 16000) &&
3517 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3518 voice_extn_compress_voip_open_input_stream(in);
3519 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003522 /* This stream could be for sound trigger lab,
3523 get sound trigger pcm if present */
3524 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303525 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003528 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003529 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
3531err_open:
3532 free(in);
3533 *stream_in = NULL;
3534 return ret;
3535}
3536
3537static void adev_close_input_stream(struct audio_hw_device *dev,
3538 struct audio_stream_in *stream)
3539{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003541 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003542 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303543
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303544 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003545
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303546 /* Disable echo reference while closing input stream */
3547 platform_set_echo_reference(adev->platform, false);
3548
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303550 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003551 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303552 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003553 if (ret != 0)
3554 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3555 __func__, ret);
3556 } else
3557 in_standby(&stream->common);
3558
Mingming Yin7b762e72015-03-04 13:47:32 -08003559 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003560 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003561 audio_extn_ssr_deinit();
3562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563
Mingming Yine62d7842013-10-25 16:26:03 -07003564 if(audio_extn_compr_cap_enabled() &&
3565 audio_extn_compr_cap_format_supported(in->config.format))
3566 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003567
3568 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 return;
3570}
3571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003572static int adev_dump(const audio_hw_device_t *device __unused,
3573 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574{
3575 return 0;
3576}
3577
3578static int adev_close(hw_device_t *device)
3579{
3580 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003581
3582 if (!adev)
3583 return 0;
3584
3585 pthread_mutex_lock(&adev_init_lock);
3586
3587 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003588 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003589 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003590 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003591 audio_route_free(adev->audio_route);
3592 free(adev->snd_dev_ref_cnt);
3593 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003594 free(device);
3595 adev = NULL;
3596 }
3597 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 return 0;
3599}
3600
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003601/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3602 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3603 * just that it _might_ work.
3604 */
3605static int period_size_is_plausible_for_low_latency(int period_size)
3606{
3607 switch (period_size) {
3608 case 160:
3609 case 240:
3610 case 320:
3611 case 480:
3612 return 1;
3613 default:
3614 return 0;
3615 }
3616}
3617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618static int adev_open(const hw_module_t *module, const char *name,
3619 hw_device_t **device)
3620{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003621 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003623 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3625
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003626 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003627 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003628 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003629 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003630 ALOGD("%s: returning existing instance of adev", __func__);
3631 ALOGD("%s: exit", __func__);
3632 pthread_mutex_unlock(&adev_init_lock);
3633 return 0;
3634 }
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev = calloc(1, sizeof(struct audio_device));
3637
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003638 if (!adev) {
3639 pthread_mutex_unlock(&adev_init_lock);
3640 return -ENOMEM;
3641 }
3642
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003643 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3646 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3647 adev->device.common.module = (struct hw_module_t *)module;
3648 adev->device.common.close = adev_close;
3649
3650 adev->device.init_check = adev_init_check;
3651 adev->device.set_voice_volume = adev_set_voice_volume;
3652 adev->device.set_master_volume = adev_set_master_volume;
3653 adev->device.get_master_volume = adev_get_master_volume;
3654 adev->device.set_master_mute = adev_set_master_mute;
3655 adev->device.get_master_mute = adev_get_master_mute;
3656 adev->device.set_mode = adev_set_mode;
3657 adev->device.set_mic_mute = adev_set_mic_mute;
3658 adev->device.get_mic_mute = adev_get_mic_mute;
3659 adev->device.set_parameters = adev_set_parameters;
3660 adev->device.get_parameters = adev_get_parameters;
3661 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3662 adev->device.open_output_stream = adev_open_output_stream;
3663 adev->device.close_output_stream = adev_close_output_stream;
3664 adev->device.open_input_stream = adev_open_input_stream;
3665 adev->device.close_input_stream = adev_close_input_stream;
3666 adev->device.dump = adev_dump;
3667
3668 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003670 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003671 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003674 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003675 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003676 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003677 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003678 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003679 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003680 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303681
3682 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3683 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003685 adev->platform = platform_init(adev);
3686 if (!adev->platform) {
3687 free(adev->snd_dev_ref_cnt);
3688 free(adev);
3689 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3690 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003691 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003692 return -EINVAL;
3693 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003694
Naresh Tanniru4c630392014-05-12 01:05:52 +05303695 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3696
Eric Laurentc4aef752013-09-12 17:45:53 -07003697 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3698 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3699 if (adev->visualizer_lib == NULL) {
3700 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3701 } else {
3702 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3703 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003704 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003705 "visualizer_hal_start_output");
3706 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003707 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003708 "visualizer_hal_stop_output");
3709 }
3710 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003711 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003712 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003713
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003714 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3715 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3716 if (adev->offload_effects_lib == NULL) {
3717 ALOGE("%s: DLOPEN failed for %s", __func__,
3718 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3719 } else {
3720 ALOGV("%s: DLOPEN successful for %s", __func__,
3721 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3722 adev->offload_effects_start_output =
3723 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3724 "offload_effects_bundle_hal_start_output");
3725 adev->offload_effects_stop_output =
3726 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3727 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003728 adev->offload_effects_set_hpx_state =
3729 (int (*)(bool))dlsym(adev->offload_effects_lib,
3730 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003731 }
3732 }
3733
Mingming Yin514a8bc2014-07-29 15:22:21 -07003734 adev->bt_wb_speech_enabled = false;
3735
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003736 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 *device = &adev->device.common;
3738
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003739 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3740 &adev->streams_output_cfg_list);
3741
Kiran Kandi910e1862013-10-29 13:29:42 -07003742 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003743
3744 char value[PROPERTY_VALUE_MAX];
3745 int trial;
3746 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3747 trial = atoi(value);
3748 if (period_size_is_plausible_for_low_latency(trial)) {
3749 pcm_config_low_latency.period_size = trial;
3750 pcm_config_low_latency.start_threshold = trial / 4;
3751 pcm_config_low_latency.avail_min = trial / 4;
3752 configured_low_latency_capture_period_size = trial;
3753 }
3754 }
3755 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3756 trial = atoi(value);
3757 if (period_size_is_plausible_for_low_latency(trial)) {
3758 configured_low_latency_capture_period_size = trial;
3759 }
3760 }
3761
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003762 pthread_mutex_unlock(&adev_init_lock);
3763
Eric Laurent994a6932013-07-17 11:51:42 -07003764 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 return 0;
3766}
3767
3768static struct hw_module_methods_t hal_module_methods = {
3769 .open = adev_open,
3770};
3771
3772struct audio_module HAL_MODULE_INFO_SYM = {
3773 .common = {
3774 .tag = HARDWARE_MODULE_TAG,
3775 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3776 .hal_api_version = HARDWARE_HAL_API_VERSION,
3777 .id = AUDIO_HARDWARE_MODULE_ID,
3778 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003779 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 .methods = &hal_module_methods,
3781 },
3782};