blob: 2d92bf8466d2a456de32f0e8d6518c0b48f3869e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
vivek mehtaa76401a2015-04-24 14:12:15 -0700255__attribute__ ((visibility ("default")))
256bool audio_hw_send_gain_dep_calibration(int level) {
257 bool ret_val = false;
258 ALOGV("%s: called ... ", __func__);
259
260 pthread_mutex_lock(&adev_init_lock);
261
262 if (adev != NULL && adev->platform != NULL) {
263 pthread_mutex_lock(&adev->lock);
264 ret_val = platform_send_gain_dep_cal(adev->platform, level);
265 pthread_mutex_unlock(&adev->lock);
266 } else {
267 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
268 }
269
270 pthread_mutex_unlock(&adev_init_lock);
271
272 return ret_val;
273}
274
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800275static int check_and_set_gapless_mode(struct audio_device *adev) {
276
277
278 char value[PROPERTY_VALUE_MAX] = {0};
279 bool gapless_enabled = false;
280 const char *mixer_ctl_name = "Compress Gapless Playback";
281 struct mixer_ctl *ctl;
282
283 ALOGV("%s:", __func__);
284 property_get("audio.offload.gapless.enabled", value, NULL);
285 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
286
287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
288 if (!ctl) {
289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
290 __func__, mixer_ctl_name);
291 return -EINVAL;
292 }
293
294 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
295 ALOGE("%s: Could not set gapless mode %d",
296 __func__, gapless_enabled);
297 return -EINVAL;
298 }
299 return 0;
300}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700302static bool is_supported_format(audio_format_t format)
303{
Eric Laurent86e17132013-09-12 17:49:30 -0700304 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 format == AUDIO_FORMAT_AAC_LC ||
306 format == AUDIO_FORMAT_AAC_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800310 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530311 format == AUDIO_FORMAT_ALAC ||
312 format == AUDIO_FORMAT_APE ||
313 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_WMA ||
315 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800316 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317
318 return false;
319}
320
321static int get_snd_codec_id(audio_format_t format)
322{
323 int id = 0;
324
Ashish Jainf9b78162014-08-25 20:36:25 +0530325 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700326 case AUDIO_FORMAT_MP3:
327 id = SND_AUDIOCODEC_MP3;
328 break;
329 case AUDIO_FORMAT_AAC:
330 id = SND_AUDIOCODEC_AAC;
331 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800333 id = SND_AUDIOCODEC_PCM;
334 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700335 case AUDIO_FORMAT_FLAC:
336 id = SND_AUDIOCODEC_FLAC;
337 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530338 case AUDIO_FORMAT_ALAC:
339 id = SND_AUDIOCODEC_ALAC;
340 break;
341 case AUDIO_FORMAT_APE:
342 id = SND_AUDIOCODEC_APE;
343 break;
344 case AUDIO_FORMAT_VORBIS:
345 id = SND_AUDIOCODEC_VORBIS;
346 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800347 case AUDIO_FORMAT_WMA:
348 id = SND_AUDIOCODEC_WMA;
349 break;
350 case AUDIO_FORMAT_WMA_PRO:
351 id = SND_AUDIOCODEC_WMA_PRO;
352 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700353 default:
Mingming Yin90310102013-11-13 16:57:00 -0800354 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700355 }
356
357 return id;
358}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800359
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530360int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530361{
362 int snd_scard_state;
363
364 if (!adev)
365 return SND_CARD_STATE_OFFLINE;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 snd_scard_state = adev->snd_card_status.state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return snd_scard_state;
372}
373
374static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
375{
376 if (!adev)
377 return -ENOSYS;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700380 if (adev->snd_card_status.state != snd_scard_state) {
381 adev->snd_card_status.state = snd_scard_state;
382 platform_snd_card_update(adev->platform, snd_scard_state);
383 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530384 pthread_mutex_unlock(&adev->snd_card_status.lock);
385
386 return 0;
387}
388
Avinash Vaish71a8b972014-07-24 15:36:33 +0530389static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
390 struct audio_usecase *uc_info)
391{
392 struct listnode *node;
393 struct audio_usecase *usecase;
394
395 if (uc_info == NULL)
396 return -EINVAL;
397
398 /* Re-route all voice usecases on the shared backend other than the
399 specified usecase to new snd devices */
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800402 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530403 enable_audio_route(adev, usecase);
404 }
405 return 0;
406}
407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700408int pcm_ioctl(struct pcm *pcm, int request, ...)
409{
410 va_list ap;
411 void * arg;
412 int pcm_fd = *(int*)pcm;
413
414 va_start(ap, request);
415 arg = va_arg(ap, void *);
416 va_end(ap);
417
418 return ioctl(pcm_fd, request, arg);
419}
420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700421int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700422 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700425 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426
427 if (usecase == NULL)
428 return -EINVAL;
429
430 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
431
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800434 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800437#ifdef DS1_DOLBY_DAP_ENABLED
438 audio_extn_dolby_set_dmid(adev);
439 audio_extn_dolby_set_endpoint(adev);
440#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700441 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530443 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700444 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700445 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700448 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
449 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 ALOGV("%s: exit", __func__);
451 return 0;
452}
453
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700454int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700455 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530460 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461 return -EINVAL;
462
463 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 if (usecase->type == PCM_CAPTURE)
465 snd_device = usecase->in_snd_device;
466 else
467 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700469 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700470 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
471 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700472 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530473 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700478int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800483 if (snd_device < SND_DEVICE_MIN ||
484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800486 return -EINVAL;
487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
489 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490
491 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
492 ALOGE("%s: Invalid sound device returned", __func__);
493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700496 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 return 0;
499 }
500
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700501 if (audio_extn_spkr_prot_is_enabled())
502 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 /* start usb playback thread */
504 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
505 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
506 audio_extn_usb_start_playback(adev);
507
508 /* start usb capture thread */
509 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
510 audio_extn_usb_start_capture(adev);
511
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800512 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
513 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700514 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700515 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
516 adev->snd_dev_ref_cnt[snd_device]--;
517 return -EINVAL;
518 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200519 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800520 if (audio_extn_spkr_prot_start_processing(snd_device)) {
521 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200522 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 return -EINVAL;
524 }
525 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
527 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700528 /* due to the possibility of calibration overwrite between listen
529 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700530 audio_extn_sound_trigger_update_device_status(snd_device,
531 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530532 audio_extn_listen_update_device_status(snd_device,
533 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700534 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700535 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 return -EINVAL;
541 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300542 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700543 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 return 0;
546}
547
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700548int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700549 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800553 if (snd_device < SND_DEVICE_MIN ||
554 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800555 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 return -EINVAL;
557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
559 ALOGE("%s: device ref cnt is already 0", __func__);
560 return -EINVAL;
561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700571 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800573 /* exit usb play back thread */
574 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
575 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
576 audio_extn_usb_stop_playback();
577
578 /* exit usb capture thread */
579 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700580 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800581
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
583 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700584 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700585 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700589
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200590 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700591 audio_extn_sound_trigger_update_device_status(snd_device,
592 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530593 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800594 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 return 0;
598}
599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600static void check_usecases_codec_backend(struct audio_device *adev,
601 struct audio_usecase *uc_info,
602 snd_device_t snd_device)
603{
604 struct listnode *node;
605 struct audio_usecase *usecase;
606 bool switch_device[AUDIO_USECASE_MAX];
607 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800608 int backend_idx = DEFAULT_CODEC_BACKEND;
609 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
611 /*
612 * This function is to make sure that all the usecases that are active on
613 * the hardware codec backend are always routed to any one device that is
614 * handled by the hardware codec.
615 * For example, if low-latency and deep-buffer usecases are currently active
616 * on speaker and out_set_parameters(headset) is received on low-latency
617 * output, then we have to make sure deep-buffer is also switched to headset,
618 * because of the limitation that both the devices cannot be enabled
619 * at the same time as they share the same backend.
620 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700621 /*
622 * This call is to check if we need to force routing for a particular stream
623 * If there is a backend configuration change for the device when a
624 * new stream starts, then ADM needs to be closed and re-opened with the new
625 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800626 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800628 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
629 snd_device);
630 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800632 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800633 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 for (i = 0; i < AUDIO_USECASE_MAX; i++)
635 switch_device[i] = false;
636
637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639
640 if (usecase == uc_info)
641 continue;
642 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
643 ALOGV("%s: backend_idx: %d,"
644 "usecase_backend_idx: %d, curr device: %s, usecase device:"
645 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530646 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800647
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800648 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700649 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
651 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530652 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700654 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700655 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 switch_device[usecase->id] = true;
657 num_uc_to_switch++;
658 }
659 }
660
661 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700662 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530664 /* Make sure the previous devices to be disabled first and then enable the
665 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
668 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
675 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700677 }
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 /* Re-route all the usecases on the shared backend other than the
681 specified usecase to new snd devices */
682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530684 /* Update the out_snd_device only for the usecases that are enabled here */
685 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
686 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530687 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 }
689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690 }
691}
692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693static void check_and_route_capture_usecases(struct audio_device *adev,
694 struct audio_usecase *uc_info,
695 snd_device_t snd_device)
696{
697 struct listnode *node;
698 struct audio_usecase *usecase;
699 bool switch_device[AUDIO_USECASE_MAX];
700 int i, num_uc_to_switch = 0;
701
702 /*
703 * This function is to make sure that all the active capture usecases
704 * are always routed to the same input sound device.
705 * For example, if audio-record and voice-call usecases are currently
706 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
707 * is received for voice call then we have to make sure that audio-record
708 * usecase is also switched to earpiece i.e. voice-dmic-ef,
709 * because of the limitation that two devices cannot be enabled
710 * at the same time if they share the same backend.
711 */
712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
713 switch_device[i] = false;
714
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700718 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700719 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700720 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
721 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700722 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700723 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
724 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700725 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 switch_device[usecase->id] = true;
728 num_uc_to_switch++;
729 }
730 }
731
732 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700733 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530735 /* Make sure the previous devices to be disabled first and then enable the
736 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 list_for_each(node, &adev->usecase_list) {
738 usecase = node_to_item(node, struct audio_usecase, list);
739 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800741 }
742 }
743
744 list_for_each(node, &adev->usecase_list) {
745 usecase = node_to_item(node, struct audio_usecase, list);
746 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700747 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 }
749 }
750
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 /* Re-route all the usecases on the shared backend other than the
752 specified usecase to new snd devices */
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 /* Update the in_snd_device only before enabling the audio route */
756 if (switch_device[usecase->id] ) {
757 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800758 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530759 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763}
764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700766static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700768 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700769 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770
771 switch (channels) {
772 /*
773 * Do not handle stereo output in Multi-channel cases
774 * Stereo case is handled in normal playback path
775 */
776 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 break;
784 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700785 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700794 ALOGE("HDMI does not support multi channel playback");
795 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796 break;
797 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700798 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799}
800
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800801audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
802 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700803{
804 struct audio_usecase *usecase;
805 struct listnode *node;
806
807 list_for_each(node, &adev->usecase_list) {
808 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800809 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700810 ALOGV("%s: usecase id %d", __func__, usecase->id);
811 return usecase->id;
812 }
813 }
814 return USECASE_INVALID;
815}
816
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700817struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700818 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
825 if (usecase->id == uc_id)
826 return usecase;
827 }
828 return NULL;
829}
830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700831int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800833 snd_device_t out_snd_device = SND_DEVICE_NONE;
834 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 struct audio_usecase *usecase = NULL;
836 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800837 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800838 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800839 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800840 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700843 usecase = get_usecase_from_list(adev, uc_id);
844 if (usecase == NULL) {
845 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
846 return -EINVAL;
847 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800850 (usecase->type == VOIP_CALL) ||
851 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700852 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800853 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700854 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase->devices = usecase->stream.out->devices;
856 } else {
857 /*
858 * If the voice call is active, use the sound devices of voice call usecase
859 * so that it would not result any device switch. All the usecases will
860 * be switched to new device when select_devices() is called for voice call
861 * usecase. This is to avoid switching devices for voice call when
862 * check_usecases_codec_backend() is called below.
863 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700864 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700865 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800866 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700867 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
868 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 in_snd_device = vc_usecase->in_snd_device;
870 out_snd_device = vc_usecase->out_snd_device;
871 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800872 } else if (voice_extn_compress_voip_is_active(adev)) {
873 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700874 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530875 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 in_snd_device = voip_usecase->in_snd_device;
878 out_snd_device = voip_usecase->out_snd_device;
879 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800880 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800881 hfp_ucid = audio_extn_hfp_get_usecase();
882 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800884 in_snd_device = hfp_usecase->in_snd_device;
885 out_snd_device = hfp_usecase->out_snd_device;
886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 }
888 if (usecase->type == PCM_PLAYBACK) {
889 usecase->devices = usecase->stream.out->devices;
890 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700892 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800893 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700894 if (usecase->stream.out == adev->primary_output &&
895 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800896 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 select_devices(adev, adev->active_input->usecase);
898 }
899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 } else if (usecase->type == PCM_CAPTURE) {
901 usecase->devices = usecase->stream.in->device;
902 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700904 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530905 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
906 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
907 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
908 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700909 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
912 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700914 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 }
917 }
918
919 if (out_snd_device == usecase->out_snd_device &&
920 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922 }
923
sangwoobc677242013-08-08 16:53:43 +0900924 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700925 out_snd_device, platform_get_snd_device_name(out_snd_device),
926 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 /*
929 * Limitation: While in call, to do a device switch we need to disable
930 * and enable both RX and TX devices though one of them is same as current
931 * device.
932 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700933 if ((usecase->type == VOICE_CALL) &&
934 (usecase->in_snd_device != SND_DEVICE_NONE) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700937 /* Disable sidetone only if voice call already exists */
938 if (voice_is_call_state_active(adev))
939 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800940 }
941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Disable current sound devices */
943 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700944 disable_audio_route(adev, usecase);
945 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 disable_audio_route(adev, usecase);
950 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951 }
952
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800953 /* Applicable only on the targets that has external modem.
954 * New device information should be sent to modem before enabling
955 * the devices to reduce in-call device switch time.
956 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700957 if ((usecase->type == VOICE_CALL) &&
958 (usecase->in_snd_device != SND_DEVICE_NONE) &&
959 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800960 status = platform_switch_voice_call_enable_device_config(adev->platform,
961 out_snd_device,
962 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800964
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700965 /* Enable new sound devices */
966 if (out_snd_device != SND_DEVICE_NONE) {
967 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
968 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970 }
971
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700972 if (in_snd_device != SND_DEVICE_NONE) {
973 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976
Avinash Vaish71a8b972014-07-24 15:36:33 +0530977 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700978 status = platform_switch_voice_call_device_post(adev->platform,
979 out_snd_device,
980 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530981 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700982 /* Enable sidetone only if voice call already exists */
983 if (voice_is_call_state_active(adev))
984 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530985 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800986
sangwoo170731f2013-06-08 15:36:36 +0900987 usecase->in_snd_device = in_snd_device;
988 usecase->out_snd_device = out_snd_device;
989
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530990 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700991 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530992 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700993 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530994 usecase->stream.out->flags,
995 usecase->stream.out->format,
996 usecase->stream.out->sample_rate,
997 usecase->stream.out->bit_width,
998 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700999 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301000 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001001
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001002 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001003
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001004 /* Applicable only on the targets that has external modem.
1005 * Enable device command should be sent to modem only after
1006 * enabling voice call mixer controls
1007 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001008 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001009 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1010 out_snd_device,
1011 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301012 ALOGD("%s: done",__func__);
1013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 return status;
1015}
1016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017static int stop_input_stream(struct stream_in *in)
1018{
1019 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 struct audio_usecase *uc_info;
1021 struct audio_device *adev = in->dev;
1022
Eric Laurentc8400632013-02-14 19:04:54 -08001023 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024
Eric Laurent994a6932013-07-17 11:51:42 -07001025 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 uc_info = get_usecase_from_list(adev, in->usecase);
1028 if (uc_info == NULL) {
1029 ALOGE("%s: Could not find the usecase (%d) in the list",
1030 __func__, in->usecase);
1031 return -EINVAL;
1032 }
1033
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001034 /* Close in-call recording streams */
1035 voice_check_and_stop_incall_rec_usecase(adev, in);
1036
Eric Laurent150dbfe2013-02-27 14:31:02 -08001037 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001038 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039
1040 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001043 list_remove(&uc_info->list);
1044 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045
Eric Laurent994a6932013-07-17 11:51:42 -07001046 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 return ret;
1048}
1049
1050int start_input_stream(struct stream_in *in)
1051{
1052 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001053 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 struct audio_usecase *uc_info;
1055 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301056 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Mingming Yine62d7842013-10-25 16:26:03 -07001058 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301059 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1060 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001061
Naresh Tanniru80659832014-06-04 18:17:56 +05301062
1063 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301064 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301065 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301066 goto error_config;
1067 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301068
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001069 /* Check if source matches incall recording usecase criteria */
1070 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1071 if (ret)
1072 goto error_config;
1073 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001074 ALOGD("%s: Updated usecase(%d: %s)",
1075 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001076
Eric Laurentb23d5282013-05-14 15:27:20 -07001077 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 if (in->pcm_device_id < 0) {
1079 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1080 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001081 ret = -EINVAL;
1082 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084
1085 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001087
1088 if (!uc_info) {
1089 ret = -ENOMEM;
1090 goto error_config;
1091 }
1092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 uc_info->id = in->usecase;
1094 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001095 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 uc_info->devices = in->device;
1097 uc_info->in_snd_device = SND_DEVICE_NONE;
1098 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001100 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301101 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103
Eric Laurentc8400632013-02-14 19:04:54 -08001104 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001105 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1106
1107 unsigned int flags = PCM_IN;
1108 unsigned int pcm_open_retry_count = 0;
1109
1110 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1111 flags |= PCM_MMAP | PCM_NOIRQ;
1112 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1113 }
1114
1115 while (1) {
1116 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1117 flags, &in->config);
1118 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1119 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1120 if (in->pcm != NULL) {
1121 pcm_close(in->pcm);
1122 in->pcm = NULL;
1123 }
1124 if (pcm_open_retry_count-- == 0) {
1125 ret = -EIO;
1126 goto error_open;
1127 }
1128 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1129 continue;
1130 }
1131 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301133 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301134
Eric Laurent994a6932013-07-17 11:51:42 -07001135 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001136 return ret;
1137
1138error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301140 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001141
1142error_config:
1143 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001145
1146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147}
1148
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001149/* must be called with out->lock locked */
1150static int send_offload_cmd_l(struct stream_out* out, int command)
1151{
1152 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1153
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001154 if (!cmd) {
1155 ALOGE("failed to allocate mem for command 0x%x", command);
1156 return -ENOMEM;
1157 }
1158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001159 ALOGVV("%s %d", __func__, command);
1160
1161 cmd->cmd = command;
1162 list_add_tail(&out->offload_cmd_list, &cmd->node);
1163 pthread_cond_signal(&out->offload_cond);
1164 return 0;
1165}
1166
1167/* must be called iwth out->lock locked */
1168static void stop_compressed_output_l(struct stream_out *out)
1169{
1170 out->offload_state = OFFLOAD_STATE_IDLE;
1171 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001172 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001173 if (out->compr != NULL) {
1174 compress_stop(out->compr);
1175 while (out->offload_thread_blocked) {
1176 pthread_cond_wait(&out->cond, &out->lock);
1177 }
1178 }
1179}
1180
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001181bool is_offload_usecase(audio_usecase_t uc_id)
1182{
1183 unsigned int i;
1184 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1185 if (uc_id == offload_usecases[i])
1186 return true;
1187 }
1188 return false;
1189}
1190
1191static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1192{
1193 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1194 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1195 char value[PROPERTY_VALUE_MAX] = {0};
1196
1197 property_get("audio.offload.multiple.enabled", value, NULL);
1198 if (!(atoi(value) || !strncmp("true", value, 4)))
1199 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1200
1201 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1202 for (i = 0; i < num_usecase; i++) {
1203 if (!(adev->offload_usecases_state & (0x1<<i))) {
1204 adev->offload_usecases_state |= 0x1 << i;
1205 ret = offload_usecases[i];
1206 break;
1207 }
1208 }
1209 ALOGV("%s: offload usecase is %d", __func__, ret);
1210 return ret;
1211}
1212
1213static void free_offload_usecase(struct audio_device *adev,
1214 audio_usecase_t uc_id)
1215{
1216 unsigned int i;
1217 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1218 if (offload_usecases[i] == uc_id) {
1219 adev->offload_usecases_state &= ~(0x1<<i);
1220 break;
1221 }
1222 }
1223 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1224}
1225
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001226static void *offload_thread_loop(void *context)
1227{
1228 struct stream_out *out = (struct stream_out *) context;
1229 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001230 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001232 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1233 set_sched_policy(0, SP_FOREGROUND);
1234 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1235
1236 ALOGV("%s", __func__);
1237 pthread_mutex_lock(&out->lock);
1238 for (;;) {
1239 struct offload_cmd *cmd = NULL;
1240 stream_callback_event_t event;
1241 bool send_callback = false;
1242
1243 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1244 __func__, list_empty(&out->offload_cmd_list),
1245 out->offload_state);
1246 if (list_empty(&out->offload_cmd_list)) {
1247 ALOGV("%s SLEEPING", __func__);
1248 pthread_cond_wait(&out->offload_cond, &out->lock);
1249 ALOGV("%s RUNNING", __func__);
1250 continue;
1251 }
1252
1253 item = list_head(&out->offload_cmd_list);
1254 cmd = node_to_item(item, struct offload_cmd, node);
1255 list_remove(item);
1256
1257 ALOGVV("%s STATE %d CMD %d out->compr %p",
1258 __func__, out->offload_state, cmd->cmd, out->compr);
1259
1260 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1261 free(cmd);
1262 break;
1263 }
1264
1265 if (out->compr == NULL) {
1266 ALOGE("%s: Compress handle is NULL", __func__);
1267 pthread_cond_signal(&out->cond);
1268 continue;
1269 }
1270 out->offload_thread_blocked = true;
1271 pthread_mutex_unlock(&out->lock);
1272 send_callback = false;
1273 switch(cmd->cmd) {
1274 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001275 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001277 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001278 send_callback = true;
1279 event = STREAM_CBK_EVENT_WRITE_READY;
1280 break;
1281 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001282 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301283 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001284 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301285 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001286 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301287 if (ret < 0)
1288 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301289 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301290 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001291 compress_drain(out->compr);
1292 else
1293 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301294 if (ret != -ENETRESET) {
1295 send_callback = true;
1296 event = STREAM_CBK_EVENT_DRAIN_READY;
1297 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1298 } else
1299 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300 break;
1301 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001302 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001304 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 send_callback = true;
1306 event = STREAM_CBK_EVENT_DRAIN_READY;
1307 break;
1308 default:
1309 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1310 break;
1311 }
1312 pthread_mutex_lock(&out->lock);
1313 out->offload_thread_blocked = false;
1314 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001315 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001316 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001318 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 free(cmd);
1320 }
1321
1322 pthread_cond_signal(&out->cond);
1323 while (!list_empty(&out->offload_cmd_list)) {
1324 item = list_head(&out->offload_cmd_list);
1325 list_remove(item);
1326 free(node_to_item(item, struct offload_cmd, node));
1327 }
1328 pthread_mutex_unlock(&out->lock);
1329
1330 return NULL;
1331}
1332
1333static int create_offload_callback_thread(struct stream_out *out)
1334{
1335 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1336 list_init(&out->offload_cmd_list);
1337 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1338 offload_thread_loop, out);
1339 return 0;
1340}
1341
1342static int destroy_offload_callback_thread(struct stream_out *out)
1343{
1344 pthread_mutex_lock(&out->lock);
1345 stop_compressed_output_l(out);
1346 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1347
1348 pthread_mutex_unlock(&out->lock);
1349 pthread_join(out->offload_thread, (void **) NULL);
1350 pthread_cond_destroy(&out->offload_cond);
1351
1352 return 0;
1353}
1354
Eric Laurent07eeafd2013-10-06 12:52:49 -07001355static bool allow_hdmi_channel_config(struct audio_device *adev)
1356{
1357 struct listnode *node;
1358 struct audio_usecase *usecase;
1359 bool ret = true;
1360
1361 list_for_each(node, &adev->usecase_list) {
1362 usecase = node_to_item(node, struct audio_usecase, list);
1363 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1364 /*
1365 * If voice call is already existing, do not proceed further to avoid
1366 * disabling/enabling both RX and TX devices, CSD calls, etc.
1367 * Once the voice call done, the HDMI channels can be configured to
1368 * max channels of remaining use cases.
1369 */
1370 if (usecase->id == USECASE_VOICE_CALL) {
1371 ALOGD("%s: voice call is active, no change in HDMI channels",
1372 __func__);
1373 ret = false;
1374 break;
1375 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1376 ALOGD("%s: multi channel playback is active, "
1377 "no change in HDMI channels", __func__);
1378 ret = false;
1379 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001380 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001381 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001382 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1383 ", no change in HDMI channels", __func__,
1384 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001385 ret = false;
1386 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 }
1388 }
1389 }
1390 return ret;
1391}
1392
1393static int check_and_set_hdmi_channels(struct audio_device *adev,
1394 unsigned int channels)
1395{
1396 struct listnode *node;
1397 struct audio_usecase *usecase;
1398
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001399 unsigned int supported_channels = platform_edid_get_max_channels(
1400 adev->platform);
1401 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 /* Check if change in HDMI channel config is allowed */
1403 if (!allow_hdmi_channel_config(adev))
1404 return 0;
1405
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001406 if (channels > supported_channels)
1407 channels = supported_channels;
1408
Eric Laurent07eeafd2013-10-06 12:52:49 -07001409 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001410 ALOGD("%s: Requested channels are same as current channels(%d)",
1411 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001412 return 0;
1413 }
1414
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001415 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001417 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001418 adev->cur_hdmi_channels = channels;
1419
1420 /*
1421 * Deroute all the playback streams routed to HDMI so that
1422 * the back end is deactivated. Note that backend will not
1423 * be deactivated if any one stream is connected to it.
1424 */
1425 list_for_each(node, &adev->usecase_list) {
1426 usecase = node_to_item(node, struct audio_usecase, list);
1427 if (usecase->type == PCM_PLAYBACK &&
1428 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001429 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 }
1431 }
1432
1433 /*
1434 * Enable all the streams disabled above. Now the HDMI backend
1435 * will be activated with new channel configuration
1436 */
1437 list_for_each(node, &adev->usecase_list) {
1438 usecase = node_to_item(node, struct audio_usecase, list);
1439 if (usecase->type == PCM_PLAYBACK &&
1440 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001441 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001442 }
1443 }
1444
1445 return 0;
1446}
1447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448static int stop_output_stream(struct stream_out *out)
1449{
1450 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 struct audio_usecase *uc_info;
1452 struct audio_device *adev = out->dev;
1453
Eric Laurent994a6932013-07-17 11:51:42 -07001454 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456 uc_info = get_usecase_from_list(adev, out->usecase);
1457 if (uc_info == NULL) {
1458 ALOGE("%s: Could not find the usecase (%d) in the list",
1459 __func__, out->usecase);
1460 return -EINVAL;
1461 }
1462
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001463 if (is_offload_usecase(out->usecase) &&
1464 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001465 if (adev->visualizer_stop_output != NULL)
1466 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001467
1468 audio_extn_dts_remove_state_notifier_node(out->usecase);
1469
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001470 if (adev->offload_effects_stop_output != NULL)
1471 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1472 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001473
Eric Laurent150dbfe2013-02-27 14:31:02 -08001474 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001475 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476
1477 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001478 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001480 list_remove(&uc_info->list);
1481 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001483 if (is_offload_usecase(out->usecase) &&
1484 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1485 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1486 ALOGV("Disable passthrough , reset mixer to pcm");
1487 /* NO_PASSTHROUGH */
1488 out->compr_config.codec->compr_passthr = 0;
1489 audio_extn_dolby_set_hdmi_config(adev, out);
1490 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1491 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001492 /* Must be called after removing the usecase from list */
1493 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1494 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1495
Eric Laurent994a6932013-07-17 11:51:42 -07001496 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 return ret;
1498}
1499
1500int start_output_stream(struct stream_out *out)
1501{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001503 int sink_channels = 0;
1504 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 struct audio_usecase *uc_info;
1506 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301507 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001509 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1510 ret = -EINVAL;
1511 goto error_config;
1512 }
1513
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301514 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1515 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1516 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301517
Naresh Tanniru80659832014-06-04 18:17:56 +05301518 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301519 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301520 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301521 goto error_config;
1522 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301523
Eric Laurentb23d5282013-05-14 15:27:20 -07001524 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 if (out->pcm_device_id < 0) {
1526 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1527 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001528 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001529 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 }
1531
1532 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001533
1534 if (!uc_info) {
1535 ret = -ENOMEM;
1536 goto error_config;
1537 }
1538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 uc_info->id = out->usecase;
1540 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001541 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 uc_info->devices = out->devices;
1543 uc_info->in_snd_device = SND_DEVICE_NONE;
1544 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001545 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001546 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001547 if (is_offload_usecase(out->usecase)) {
1548 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001549 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1550 }
1551 }
Mingming Yin9c041392014-05-01 15:37:31 -07001552 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1553 if (!strncmp("true", prop_value, 4)) {
1554 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001555 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1556 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001557 check_and_set_hdmi_channels(adev, sink_channels);
1558 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001559 if (is_offload_usecase(out->usecase)) {
1560 unsigned int ch_count = out->compr_config.codec->ch_in;
1561 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1562 /* backend channel config for passthrough stream is stereo */
1563 ch_count = 2;
1564 check_and_set_hdmi_channels(adev, ch_count);
1565 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001566 check_and_set_hdmi_channels(adev, out->config.channels);
1567 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001568 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001569 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001570 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 select_devices(adev, out->usecase);
1573
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001574 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1575 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001576 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001577 unsigned int flags = PCM_OUT;
1578 unsigned int pcm_open_retry_count = 0;
1579 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1580 flags |= PCM_MMAP | PCM_NOIRQ;
1581 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1582 } else
1583 flags |= PCM_MONOTONIC;
1584
1585 while (1) {
1586 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1587 flags, &out->config);
1588 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1589 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1590 if (out->pcm != NULL) {
1591 pcm_close(out->pcm);
1592 out->pcm = NULL;
1593 }
1594 if (pcm_open_retry_count-- == 0) {
1595 ret = -EIO;
1596 goto error_open;
1597 }
1598 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1599 continue;
1600 }
1601 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001602 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001603 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1604 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001605 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001606 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1607 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001609 out->compr = compress_open(adev->snd_card,
1610 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001611 COMPRESS_IN, &out->compr_config);
1612 if (out->compr && !is_compress_ready(out->compr)) {
1613 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1614 compress_close(out->compr);
1615 out->compr = NULL;
1616 ret = -EIO;
1617 goto error_open;
1618 }
1619 if (out->offload_callback)
1620 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001621
Fred Oh3f43e742015-03-04 18:42:34 -08001622 /* Since small bufs uses blocking writes, a write will be blocked
1623 for the default max poll time (20s) in the event of an SSR.
1624 Reduce the poll time to observe and deal with SSR faster.
1625 */
1626 if (out->use_small_bufs) {
1627 compress_set_max_poll_wait(out->compr, 1000);
1628 }
1629
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001630 audio_extn_dts_create_state_notifier_node(out->usecase);
1631 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1632 popcount(out->channel_mask),
1633 out->playback_started);
1634
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001635#ifdef DS1_DOLBY_DDP_ENABLED
1636 if (audio_extn_is_dolby_format(out->format))
1637 audio_extn_dolby_send_ddp_endp_params(adev);
1638#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001639 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1640 if (adev->visualizer_start_output != NULL)
1641 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1642 if (adev->offload_effects_start_output != NULL)
1643 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001644 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
Eric Laurent994a6932013-07-17 11:51:42 -07001647 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001649error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001651error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001652 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653}
1654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655static int check_input_parameters(uint32_t sample_rate,
1656 audio_format_t format,
1657 int channel_count)
1658{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001659 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001661 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001662 !voice_extn_compress_voip_is_format_supported(format) &&
1663 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001664
1665 switch (channel_count) {
1666 case 1:
1667 case 2:
1668 case 6:
1669 break;
1670 default:
1671 ret = -EINVAL;
1672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
1674 switch (sample_rate) {
1675 case 8000:
1676 case 11025:
1677 case 12000:
1678 case 16000:
1679 case 22050:
1680 case 24000:
1681 case 32000:
1682 case 44100:
1683 case 48000:
1684 break;
1685 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001686 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 }
1688
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001689 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690}
1691
1692static size_t get_input_buffer_size(uint32_t sample_rate,
1693 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001694 int channel_count,
1695 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696{
1697 size_t size = 0;
1698
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001699 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1700 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001702 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001703 if (is_low_latency)
1704 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001705 /* ToDo: should use frame_size computed based on the format and
1706 channel_count here. */
1707 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001709 /* make sure the size is multiple of 32 bytes
1710 * At 48 kHz mono 16-bit PCM:
1711 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1712 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1713 */
1714 size += 0x1f;
1715 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001716
1717 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718}
1719
1720static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1721{
1722 struct stream_out *out = (struct stream_out *)stream;
1723
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725}
1726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001727static int out_set_sample_rate(struct audio_stream *stream __unused,
1728 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729{
1730 return -ENOSYS;
1731}
1732
1733static size_t out_get_buffer_size(const struct audio_stream *stream)
1734{
1735 struct stream_out *out = (struct stream_out *)stream;
1736
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001737 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001739 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1740 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001742 return out->config.period_size *
1743 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744}
1745
1746static uint32_t out_get_channels(const struct audio_stream *stream)
1747{
1748 struct stream_out *out = (struct stream_out *)stream;
1749
1750 return out->channel_mask;
1751}
1752
1753static audio_format_t out_get_format(const struct audio_stream *stream)
1754{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 struct stream_out *out = (struct stream_out *)stream;
1756
1757 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758}
1759
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001760static int out_set_format(struct audio_stream *stream __unused,
1761 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762{
1763 return -ENOSYS;
1764}
1765
1766static int out_standby(struct audio_stream *stream)
1767{
1768 struct stream_out *out = (struct stream_out *)stream;
1769 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301771 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1772 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001773 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1774 /* Ignore standby in case of voip call because the voip output
1775 * stream is closed in adev_close_output_stream()
1776 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301777 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001778 return 0;
1779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001783 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001785 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 if (out->pcm) {
1787 pcm_close(out->pcm);
1788 out->pcm = NULL;
1789 }
1790 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001791 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 out->gapless_mdata.encoder_delay = 0;
1794 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 if (out->compr != NULL) {
1796 compress_close(out->compr);
1797 out->compr = NULL;
1798 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001799 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 }
1803 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001804 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 return 0;
1806}
1807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001808static int out_dump(const struct audio_stream *stream __unused,
1809 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810{
1811 return 0;
1812}
1813
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1815{
1816 int ret = 0;
1817 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001818 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001819
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001821 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 return -EINVAL;
1823 }
1824
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001825 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1826 if (ret >= 0) {
1827 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1828 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1829 ALOGV("ADTS format is set in offload mode");
1830 }
1831 out->send_new_metadata = 1;
1832 }
1833
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301834 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001835
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001836 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1837 if(ret >= 0)
1838 is_meta_data_params = true;
1839 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301840 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001841 is_meta_data_params = true;
1842 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301843 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001844 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001845 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1846 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001847 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301848 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1851 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001852 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301853 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854 }
1855
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001856 if(!is_meta_data_params) {
1857 ALOGV("%s: Not gapless meta data params", __func__);
1858 return 0;
1859 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 out->send_new_metadata = 1;
1861 ALOGV("%s new encoder delay %u and padding %u", __func__,
1862 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1863
1864 return 0;
1865}
1866
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001867static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1868{
1869 return out == adev->primary_output || out == adev->voice_tx_output;
1870}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1873{
1874 struct stream_out *out = (struct stream_out *)stream;
1875 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001876 struct audio_usecase *usecase;
1877 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 struct str_parms *parms;
1879 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001880 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001881 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882
sangwoobc677242013-08-08 16:53:43 +09001883 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001884 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301886 if (!parms)
1887 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001888 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1889 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001892 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301895 * When HDMI cable is unplugged/usb hs is disconnected the
1896 * music playback is paused and the policy manager sends routing=0
1897 * But the audioflingercontinues to write data until standby time
1898 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 * Avoid this by routing audio to speaker until standby.
1900 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301901 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1902 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001904 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1905 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 }
1907
1908 /*
1909 * select_devices() call below switches all the usecases on the same
1910 * backend to the new device. Refer to check_usecases_codec_backend() in
1911 * the select_devices(). But how do we undo this?
1912 *
1913 * For example, music playback is active on headset (deep-buffer usecase)
1914 * and if we go to ringtones and select a ringtone, low-latency usecase
1915 * will be started on headset+speaker. As we can't enable headset+speaker
1916 * and headset devices at the same time, select_devices() switches the music
1917 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1918 * So when the ringtone playback is completed, how do we undo the same?
1919 *
1920 * We are relying on the out_set_parameters() call on deep-buffer output,
1921 * once the ringtone playback is ended.
1922 * NOTE: We should not check if the current devices are same as new devices.
1923 * Because select_devices() must be called to switch back the music
1924 * playback to headset.
1925 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001926 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 out->devices = val;
1928
1929 if (!out->standby)
1930 select_devices(adev, out->usecase);
1931
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001932 if (output_drives_call(adev, out)) {
1933 if(!voice_is_in_call(adev)) {
1934 if (adev->mode == AUDIO_MODE_IN_CALL) {
1935 adev->current_call_output = out;
1936 ret = voice_start_call(adev);
1937 }
1938 } else {
1939 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001940 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001941 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001942 }
1943 }
1944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001946 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001948
1949 if (out == adev->primary_output) {
1950 pthread_mutex_lock(&adev->lock);
1951 audio_extn_set_parameters(adev, parms);
1952 pthread_mutex_unlock(&adev->lock);
1953 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001955 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001956 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001957
1958 audio_extn_dts_create_state_notifier_node(out->usecase);
1959 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1960 popcount(out->channel_mask),
1961 out->playback_started);
1962
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001963 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001964 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301967error:
Eric Laurent994a6932013-07-17 11:51:42 -07001968 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 return ret;
1970}
1971
1972static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1973{
1974 struct stream_out *out = (struct stream_out *)stream;
1975 struct str_parms *query = str_parms_create_str(keys);
1976 char *str;
1977 char value[256];
1978 struct str_parms *reply = str_parms_create();
1979 size_t i, j;
1980 int ret;
1981 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001982
1983 if (!query || !reply) {
1984 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1985 return NULL;
1986 }
1987
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1990 if (ret >= 0) {
1991 value[0] = '\0';
1992 i = 0;
1993 while (out->supported_channel_masks[i] != 0) {
1994 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1995 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1996 if (!first) {
1997 strcat(value, "|");
1998 }
1999 strcat(value, out_channels_name_to_enum_table[j].name);
2000 first = false;
2001 break;
2002 }
2003 }
2004 i++;
2005 }
2006 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2007 str = str_parms_to_str(reply);
2008 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002009 voice_extn_out_get_parameters(out, query, reply);
2010 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002011 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002012 free(str);
2013 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002016
2017 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2018 if (ret >= 0) {
2019 value[0] = '\0';
2020 i = 0;
2021 first = true;
2022 while (out->supported_formats[i] != 0) {
2023 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2024 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2025 if (!first) {
2026 strcat(value, "|");
2027 }
2028 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2029 first = false;
2030 break;
2031 }
2032 }
2033 i++;
2034 }
2035 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2036 str = str_parms_to_str(reply);
2037 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 str_parms_destroy(query);
2039 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002040 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 return str;
2042}
2043
2044static uint32_t out_get_latency(const struct audio_stream_out *stream)
2045{
2046 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002047 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Alexy Josephaa54c872014-12-03 02:46:47 -08002049 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002050 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002051 } else {
2052 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002054 }
2055
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302056 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002057 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058}
2059
2060static int out_set_volume(struct audio_stream_out *stream, float left,
2061 float right)
2062{
Eric Laurenta9024de2013-04-04 09:19:12 -07002063 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 int volume[2];
2065
Eric Laurenta9024de2013-04-04 09:19:12 -07002066 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2067 /* only take left channel into account: the API is for stereo anyway */
2068 out->muted = (left == 0.0f);
2069 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002070 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002071 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2072 /*
2073 * Set mute or umute on HDMI passthrough stream.
2074 * Only take left channel into account.
2075 * Mute is 0 and unmute 1
2076 */
2077 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2078 } else {
2079 char mixer_ctl_name[128];
2080 struct audio_device *adev = out->dev;
2081 struct mixer_ctl *ctl;
2082 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002083 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002085 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2086 "Compress Playback %d Volume", pcm_device_id);
2087 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2088 if (!ctl) {
2089 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2090 __func__, mixer_ctl_name);
2091 return -EINVAL;
2092 }
2093 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2094 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2095 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2096 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002098 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 return -ENOSYS;
2101}
2102
2103static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2104 size_t bytes)
2105{
2106 struct stream_out *out = (struct stream_out *)stream;
2107 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302108 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002109 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302112
Naresh Tanniru80659832014-06-04 18:17:56 +05302113 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002114 // increase written size during SSR to avoid mismatch
2115 // with the written frames count in AF
2116 if (!is_offload_usecase(out->usecase))
2117 out->written += bytes / (out->config.channels * sizeof(short));
2118
Naresh Tanniru80659832014-06-04 18:17:56 +05302119 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302120 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302121 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302122 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002123 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302124 //during SSR for compress usecase we should return error to flinger
2125 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2126 pthread_mutex_unlock(&out->lock);
2127 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302128 }
2129 }
2130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002132 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002133 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002134 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2135 ret = voice_extn_compress_voip_start_output_stream(out);
2136 else
2137 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002138 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002141 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 goto exit;
2143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002146 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002147 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002148 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002149 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2151 out->send_new_metadata = 0;
2152 }
2153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302155 if (ret < 0)
2156 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002157 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002158 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302159 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302161 } else if (-ENETRESET == ret) {
2162 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2163 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2164 pthread_mutex_unlock(&out->lock);
2165 out_standby(&out->stream.common);
2166 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302168 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002170 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 out->playback_started = 1;
2172 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002173
2174 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2175 popcount(out->channel_mask),
2176 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 }
2178 pthread_mutex_unlock(&out->lock);
2179 return ret;
2180 } else {
2181 if (out->pcm) {
2182 if (out->muted)
2183 memset((void *)buffer, 0, bytes);
2184 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002185 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2186 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2187 else
2188 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302189 if (ret < 0)
2190 ret = -errno;
2191 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002192 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
2195
2196exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302197 /* ToDo: There may be a corner case when SSR happens back to back during
2198 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302199 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302200 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302201 }
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 pthread_mutex_unlock(&out->lock);
2204
2205 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002206 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002207 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302208 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302209 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302210 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302211 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302212 out->standby = true;
2213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002215 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302216 out_get_sample_rate(&out->stream.common));
2217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 }
2219 return bytes;
2220}
2221
2222static int out_get_render_position(const struct audio_stream_out *stream,
2223 uint32_t *dsp_frames)
2224{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302226 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002227
2228 if (dsp_frames == NULL)
2229 return -EINVAL;
2230
2231 *dsp_frames = 0;
2232 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002233 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 pthread_mutex_lock(&out->lock);
2235 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302236 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302238 if (ret < 0)
2239 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 ALOGVV("%s rendered frames %d sample_rate %d",
2241 __func__, *dsp_frames, out->sample_rate);
2242 }
2243 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302244 if (-ENETRESET == ret) {
2245 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2246 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2247 return -EINVAL;
2248 } else if(ret < 0) {
2249 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2250 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302251 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2252 /*
2253 * Handle corner case where compress session is closed during SSR
2254 * and timestamp is queried
2255 */
2256 ALOGE(" ERROR: sound card not active, return error");
2257 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302258 } else {
2259 return 0;
2260 }
Zhou Song32a556e2015-05-05 10:46:56 +08002261 } else if (audio_is_linear_pcm(out->format)) {
2262 *dsp_frames = out->written;
2263 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 } else
2265 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266}
2267
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002268static int out_add_audio_effect(const struct audio_stream *stream __unused,
2269 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270{
2271 return 0;
2272}
2273
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002274static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2275 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276{
2277 return 0;
2278}
2279
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002280static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2281 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282{
2283 return -EINVAL;
2284}
2285
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002286static int out_get_presentation_position(const struct audio_stream_out *stream,
2287 uint64_t *frames, struct timespec *timestamp)
2288{
2289 struct stream_out *out = (struct stream_out *)stream;
2290 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002291 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002292
2293 pthread_mutex_lock(&out->lock);
2294
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002295 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002296 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302297 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002298 &out->sample_rate);
2299 ALOGVV("%s rendered frames %ld sample_rate %d",
2300 __func__, dsp_frames, out->sample_rate);
2301 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302302 if (ret < 0)
2303 ret = -errno;
2304 if (-ENETRESET == ret) {
2305 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2306 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2307 ret = -EINVAL;
2308 } else
2309 ret = 0;
2310
Eric Laurent949a0892013-09-20 09:20:13 -07002311 /* this is the best we can do */
2312 clock_gettime(CLOCK_MONOTONIC, timestamp);
2313 }
2314 } else {
2315 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002316 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002317 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2318 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002319 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002320 // This adjustment accounts for buffering after app processor.
2321 // It is based on estimated DSP latency per use case, rather than exact.
2322 signed_frames -=
2323 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2324
Eric Laurent949a0892013-09-20 09:20:13 -07002325 // It would be unusual for this value to be negative, but check just in case ...
2326 if (signed_frames >= 0) {
2327 *frames = signed_frames;
2328 ret = 0;
2329 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002330 }
2331 }
2332 }
2333
2334 pthread_mutex_unlock(&out->lock);
2335
2336 return ret;
2337}
2338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339static int out_set_callback(struct audio_stream_out *stream,
2340 stream_callback_t callback, void *cookie)
2341{
2342 struct stream_out *out = (struct stream_out *)stream;
2343
2344 ALOGV("%s", __func__);
2345 pthread_mutex_lock(&out->lock);
2346 out->offload_callback = callback;
2347 out->offload_cookie = cookie;
2348 pthread_mutex_unlock(&out->lock);
2349 return 0;
2350}
2351
2352static int out_pause(struct audio_stream_out* stream)
2353{
2354 struct stream_out *out = (struct stream_out *)stream;
2355 int status = -ENOSYS;
2356 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002357 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002358 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 pthread_mutex_lock(&out->lock);
2360 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302361 struct audio_device *adev = out->dev;
2362 int snd_scard_state = get_snd_card_state(adev);
2363
2364 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2365 status = compress_pause(out->compr);
2366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002368
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302369 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002370 audio_extn_dts_notify_playback_state(out->usecase, 0,
2371 out->sample_rate, popcount(out->channel_mask),
2372 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 }
2374 pthread_mutex_unlock(&out->lock);
2375 }
2376 return status;
2377}
2378
2379static int out_resume(struct audio_stream_out* stream)
2380{
2381 struct stream_out *out = (struct stream_out *)stream;
2382 int status = -ENOSYS;
2383 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002384 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002385 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 status = 0;
2387 pthread_mutex_lock(&out->lock);
2388 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302389 struct audio_device *adev = out->dev;
2390 int snd_scard_state = get_snd_card_state(adev);
2391
2392 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2393 status = compress_resume(out->compr);
2394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002396
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302397 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002398 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2399 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 }
2401 pthread_mutex_unlock(&out->lock);
2402 }
2403 return status;
2404}
2405
2406static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409 int status = -ENOSYS;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 pthread_mutex_lock(&out->lock);
2413 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2414 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2415 else
2416 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2417 pthread_mutex_unlock(&out->lock);
2418 }
2419 return status;
2420}
2421
2422static int out_flush(struct audio_stream_out* stream)
2423{
2424 struct stream_out *out = (struct stream_out *)stream;
2425 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002426 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002427 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 pthread_mutex_lock(&out->lock);
2429 stop_compressed_output_l(out);
2430 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002431 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 return 0;
2433 }
2434 return -ENOSYS;
2435}
2436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437/** audio_stream_in implementation **/
2438static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2439{
2440 struct stream_in *in = (struct stream_in *)stream;
2441
2442 return in->config.rate;
2443}
2444
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002445static int in_set_sample_rate(struct audio_stream *stream __unused,
2446 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447{
2448 return -ENOSYS;
2449}
2450
2451static size_t in_get_buffer_size(const struct audio_stream *stream)
2452{
2453 struct stream_in *in = (struct stream_in *)stream;
2454
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002455 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2456 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002457 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2458 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002460 return in->config.period_size *
2461 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462}
2463
2464static uint32_t in_get_channels(const struct audio_stream *stream)
2465{
2466 struct stream_in *in = (struct stream_in *)stream;
2467
2468 return in->channel_mask;
2469}
2470
2471static audio_format_t in_get_format(const struct audio_stream *stream)
2472{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002473 struct stream_in *in = (struct stream_in *)stream;
2474
2475 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476}
2477
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002478static int in_set_format(struct audio_stream *stream __unused,
2479 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480{
2481 return -ENOSYS;
2482}
2483
2484static int in_standby(struct audio_stream *stream)
2485{
2486 struct stream_in *in = (struct stream_in *)stream;
2487 struct audio_device *adev = in->dev;
2488 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302489 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2490 stream, in->usecase, use_case_table[in->usecase]);
2491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002492 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2493 /* Ignore standby in case of voip call because the voip input
2494 * stream is closed in adev_close_input_stream()
2495 */
2496 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2497 return status;
2498 }
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002501 if (!in->standby && in->is_st_session) {
2502 ALOGD("%s: sound trigger pcm stop lab", __func__);
2503 audio_extn_sound_trigger_stop_lab(in);
2504 in->standby = 1;
2505 }
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002508 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002510 if (in->pcm) {
2511 pcm_close(in->pcm);
2512 in->pcm = NULL;
2513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002515 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 }
2517 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002518 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 return status;
2520}
2521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002522static int in_dump(const struct audio_stream *stream __unused,
2523 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524{
2525 return 0;
2526}
2527
2528static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2529{
2530 struct stream_in *in = (struct stream_in *)stream;
2531 struct audio_device *adev = in->dev;
2532 struct str_parms *parms;
2533 char *str;
2534 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002535 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302537 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 parms = str_parms_create_str(kvpairs);
2539
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302540 if (!parms)
2541 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002543 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002544
2545 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2546 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 val = atoi(value);
2548 /* no audio source uses val == 0 */
2549 if ((in->source != val) && (val != 0)) {
2550 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002551 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2552 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2553 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2554 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002555 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002556 err = voice_extn_compress_voip_open_input_stream(in);
2557 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002558 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002559 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002560 }
2561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 }
2563 }
2564
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002565 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2566 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002568 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 in->device = val;
2570 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002571 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002572 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 }
2574 }
2575
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002576done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002578 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579
2580 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302581error:
Eric Laurent994a6932013-07-17 11:51:42 -07002582 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 return ret;
2584}
2585
2586static char* in_get_parameters(const struct audio_stream *stream,
2587 const char *keys)
2588{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002589 struct stream_in *in = (struct stream_in *)stream;
2590 struct str_parms *query = str_parms_create_str(keys);
2591 char *str;
2592 char value[256];
2593 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002594
2595 if (!query || !reply) {
2596 ALOGE("in_get_parameters: failed to create query or reply");
2597 return NULL;
2598 }
2599
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002600 ALOGV("%s: enter: keys - %s", __func__, keys);
2601
2602 voice_extn_in_get_parameters(in, query, reply);
2603
2604 str = str_parms_to_str(reply);
2605 str_parms_destroy(query);
2606 str_parms_destroy(reply);
2607
2608 ALOGV("%s: exit: returns - %s", __func__, str);
2609 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610}
2611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002612static int in_set_gain(struct audio_stream_in *stream __unused,
2613 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614{
2615 return 0;
2616}
2617
2618static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2619 size_t bytes)
2620{
2621 struct stream_in *in = (struct stream_in *)stream;
2622 struct audio_device *adev = in->dev;
2623 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302624 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302627
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002628 if (in->is_st_session) {
2629 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2630 /* Read from sound trigger HAL */
2631 audio_extn_sound_trigger_read(in, buffer, bytes);
2632 pthread_mutex_unlock(&in->lock);
2633 return bytes;
2634 }
2635
2636 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2637 ALOGD(" %s: sound card is not active/SSR state", __func__);
2638 ret= -EIO;;
2639 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302640 }
2641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002643 pthread_mutex_lock(&adev->lock);
2644 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2645 ret = voice_extn_compress_voip_start_input_stream(in);
2646 else
2647 ret = start_input_stream(in);
2648 pthread_mutex_unlock(&adev->lock);
2649 if (ret != 0) {
2650 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652 in->standby = 0;
2653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654
2655 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002656 if (audio_extn_ssr_get_enabled() &&
2657 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002658 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002659 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2660 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002661 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2662 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002663 else
2664 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302665 if (ret < 0)
2666 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668
2669 /*
2670 * Instead of writing zeroes here, we could trust the hardware
2671 * to always provide zeroes when muted.
2672 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302673 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2674 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 memset(buffer, 0, bytes);
2676
2677exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302678 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302679 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002680 if (-ENETRESET == ret)
2681 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 pthread_mutex_unlock(&in->lock);
2684
2685 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302686 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302687 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302688 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302689 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302690 in->standby = true;
2691 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302692 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002694 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002695 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302696 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 }
2698 return bytes;
2699}
2700
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002701static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
2703 return 0;
2704}
2705
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002706static int add_remove_audio_effect(const struct audio_stream *stream,
2707 effect_handle_t effect,
2708 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710 struct stream_in *in = (struct stream_in *)stream;
2711 int status = 0;
2712 effect_descriptor_t desc;
2713
2714 status = (*effect)->get_descriptor(effect, &desc);
2715 if (status != 0)
2716 return status;
2717
2718 pthread_mutex_lock(&in->lock);
2719 pthread_mutex_lock(&in->dev->lock);
2720 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2721 in->enable_aec != enable &&
2722 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2723 in->enable_aec = enable;
2724 if (!in->standby)
2725 select_devices(in->dev, in->usecase);
2726 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002727 if (in->enable_ns != enable &&
2728 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2729 in->enable_ns = enable;
2730 if (!in->standby)
2731 select_devices(in->dev, in->usecase);
2732 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002733 pthread_mutex_unlock(&in->dev->lock);
2734 pthread_mutex_unlock(&in->lock);
2735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 return 0;
2737}
2738
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002739static int in_add_audio_effect(const struct audio_stream *stream,
2740 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741{
Eric Laurent994a6932013-07-17 11:51:42 -07002742 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002743 return add_remove_audio_effect(stream, effect, true);
2744}
2745
2746static int in_remove_audio_effect(const struct audio_stream *stream,
2747 effect_handle_t effect)
2748{
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002750 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751}
2752
2753static int adev_open_output_stream(struct audio_hw_device *dev,
2754 audio_io_handle_t handle,
2755 audio_devices_t devices,
2756 audio_output_flags_t flags,
2757 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002758 struct audio_stream_out **stream_out,
2759 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760{
2761 struct audio_device *adev = (struct audio_device *)dev;
2762 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002763 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002764 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302767
2768 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2769 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2770 ALOGE(" sound card is not active rejecting compress output open request");
2771 return -EINVAL;
2772 }
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2775
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302776 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2777 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2778 devices, flags, &out->stream);
2779
2780
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002781 if (!out) {
2782 return -ENOMEM;
2783 }
2784
Haynes Mathew George204045b2015-02-25 20:32:03 -08002785 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2786 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 if (devices == AUDIO_DEVICE_NONE)
2789 devices = AUDIO_DEVICE_OUT_SPEAKER;
2790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 out->flags = flags;
2792 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002793 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002794 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002795 out->sample_rate = config->sample_rate;
2796 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2797 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002798 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002799 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002800 out->non_blocking = 0;
2801 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802
2803 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002804 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2805 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002806 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2807 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2808
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002809 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002810 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2811 ret = read_hdmi_channel_masks(out);
2812
2813 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2814 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002815 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002816 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002817 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002818
2819 if (config->sample_rate == 0)
2820 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2821 if (config->channel_mask == 0)
2822 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2823
2824 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2827 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002829 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002831 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2832 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002833 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002834 ret = voice_extn_compress_voip_open_output_stream(out);
2835 if (ret != 0) {
2836 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2837 __func__, ret);
2838 goto error_open;
2839 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2841 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2842 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2843 ALOGE("%s: Unsupported Offload information", __func__);
2844 ret = -EINVAL;
2845 goto error_open;
2846 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002847
2848 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2849 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2850 ALOGV("read and update_pass through formats");
2851 ret = audio_extn_dolby_update_passt_formats(adev, out);
2852 if(ret != 0) {
2853 goto error_open;
2854 }
2855 if(config->offload_info.format == 0)
2856 config->offload_info.format = out->supported_formats[0];
2857 }
2858
Mingming Yin90310102013-11-13 16:57:00 -08002859 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002860 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 ALOGE("%s: Unsupported audio format", __func__);
2862 ret = -EINVAL;
2863 goto error_open;
2864 }
2865
2866 out->compr_config.codec = (struct snd_codec *)
2867 calloc(1, sizeof(struct snd_codec));
2868
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002869 if (!out->compr_config.codec) {
2870 ret = -ENOMEM;
2871 goto error_open;
2872 }
2873
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002874 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 if (config->offload_info.channel_mask)
2876 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002877 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002879 config->offload_info.channel_mask = config->channel_mask;
2880 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002881 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->sample_rate = config->offload_info.sample_rate;
2883
2884 out->stream.set_callback = out_set_callback;
2885 out->stream.pause = out_pause;
2886 out->stream.resume = out_resume;
2887 out->stream.drain = out_drain;
2888 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002889 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002891 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002892 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002893 audio_extn_dolby_get_snd_codec_id(adev, out,
2894 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002895 else
2896 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat2ec445f2015-07-23 18:02:31 +05302898 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002900 platform_get_pcm_offload_buffer_size(&config->offload_info);
2901 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2902 out->compr_config.fragment_size =
2903 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002904 } else {
2905 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002907 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2909 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002910 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 out->compr_config.codec->bit_rate =
2912 config->offload_info.bit_rate;
2913 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002914 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002916 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002917 /*TODO: Do we need to change it for passthrough */
2918 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919
Mingming Yin3ee55c62014-08-04 14:23:35 -07002920 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2921 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002922 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2923 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002924 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002925 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2926
Mingming Yin3ee55c62014-08-04 14:23:35 -07002927 if (out->bit_width == 24) {
2928 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2929 }
2930
Amit Shekhar6f461b12014-08-01 14:52:58 -07002931 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002932 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2935 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002936
Mingming Yin497419f2015-07-01 16:57:32 -07002937 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002938 //this flag is set from framework only if its for PCM formats
2939 //no need to check for PCM format again
2940 out->non_blocking = 0;
2941 out->use_small_bufs = true;
2942 ALOGI("Keep write blocking for small buff: non_blockling %d",
2943 out->non_blocking);
2944 }
2945
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002946 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002947 out->offload_state = OFFLOAD_STATE_IDLE;
2948 out->playback_started = 0;
2949
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002950 audio_extn_dts_create_state_notifier_node(out->usecase);
2951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 create_offload_callback_thread(out);
2953 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2954 __func__, config->offload_info.version,
2955 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002956 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002957 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002958 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2959 ret = voice_check_and_set_incall_music_usecase(adev, out);
2960 if (ret != 0) {
2961 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2962 __func__, ret);
2963 goto error_open;
2964 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002965 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2966 if (config->sample_rate == 0)
2967 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2968 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2969 config->sample_rate != 8000) {
2970 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2971 ret = -EINVAL;
2972 goto error_open;
2973 }
2974 out->sample_rate = config->sample_rate;
2975 out->config.rate = config->sample_rate;
2976 if (config->format == AUDIO_FORMAT_DEFAULT)
2977 config->format = AUDIO_FORMAT_PCM_16_BIT;
2978 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2979 config->format = AUDIO_FORMAT_PCM_16_BIT;
2980 ret = -EINVAL;
2981 goto error_open;
2982 }
2983 out->format = config->format;
2984 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2985 out->config = pcm_config_afe_proxy_playback;
2986 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002987 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002988 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2990 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002991 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002992 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2993 format = AUDIO_FORMAT_PCM_16_BIT;
2994 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2995 out->config = pcm_config_deep_buffer;
2996 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002997 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002998 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002999 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003000 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003001 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003002 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 }
3004
Amit Shekhar1d896042014-10-03 13:16:09 -07003005 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3006 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003007 /* TODO remove this hardcoding and check why width is zero*/
3008 if (out->bit_width == 0)
3009 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003010 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3011 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003012 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003013 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003014 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3015 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3016 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003017 if(adev->primary_output == NULL)
3018 adev->primary_output = out;
3019 else {
3020 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003021 ret = -EEXIST;
3022 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003023 }
3024 }
3025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 /* Check if this usecase is already existing */
3027 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003028 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3029 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003032 ret = -EEXIST;
3033 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 }
3035 pthread_mutex_unlock(&adev->lock);
3036
3037 out->stream.common.get_sample_rate = out_get_sample_rate;
3038 out->stream.common.set_sample_rate = out_set_sample_rate;
3039 out->stream.common.get_buffer_size = out_get_buffer_size;
3040 out->stream.common.get_channels = out_get_channels;
3041 out->stream.common.get_format = out_get_format;
3042 out->stream.common.set_format = out_set_format;
3043 out->stream.common.standby = out_standby;
3044 out->stream.common.dump = out_dump;
3045 out->stream.common.set_parameters = out_set_parameters;
3046 out->stream.common.get_parameters = out_get_parameters;
3047 out->stream.common.add_audio_effect = out_add_audio_effect;
3048 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3049 out->stream.get_latency = out_get_latency;
3050 out->stream.set_volume = out_set_volume;
3051 out->stream.write = out_write;
3052 out->stream.get_render_position = out_get_render_position;
3053 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003054 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003057 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003058 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059
3060 config->format = out->stream.common.get_format(&out->stream.common);
3061 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3062 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3063
3064 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303065 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3066 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003067
3068 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3069 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3070 popcount(out->channel_mask), out->playback_started);
3071
Eric Laurent994a6932013-07-17 11:51:42 -07003072 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003074
3075error_open:
3076 free(out);
3077 *stream_out = NULL;
3078 ALOGD("%s: exit: ret %d", __func__, ret);
3079 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080}
3081
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003082static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 struct audio_stream_out *stream)
3084{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 struct stream_out *out = (struct stream_out *)stream;
3086 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303089 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3090
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003091 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303092 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003093 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303094 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 if(ret != 0)
3096 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3097 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003098 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003099 out_standby(&stream->common);
3100
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003101 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003102 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003104 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 if (out->compr_config.codec != NULL)
3106 free(out->compr_config.codec);
3107 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003108
3109 if (adev->voice_tx_output == out)
3110 adev->voice_tx_output = NULL;
3111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 pthread_cond_destroy(&out->cond);
3113 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003115 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116}
3117
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003118static void close_compress_sessions(struct audio_device *adev)
3119{
Mingming Yin7b762e72015-03-04 13:47:32 -08003120 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303121 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003122 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003123 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303124
3125 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003126 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303127 if (is_offload_usecase(usecase->id)) {
3128 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003129 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3130 out = usecase->stream.out;
3131 pthread_mutex_unlock(&adev->lock);
3132 out_standby(&out->stream.common);
3133 pthread_mutex_lock(&adev->lock);
3134 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303135 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003136 }
3137 pthread_mutex_unlock(&adev->lock);
3138}
3139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3141{
3142 struct audio_device *adev = (struct audio_device *)dev;
3143 struct str_parms *parms;
3144 char *str;
3145 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003146 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003147 int ret;
3148 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003150 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303153 if (!parms)
3154 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003155 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3156 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303157 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303159 struct listnode *node;
3160 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303161 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303162 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003163 //close compress sessions on OFFLINE status
3164 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303165 } else if (strstr(snd_card_status, "ONLINE")) {
3166 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303167 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003168 //send dts hpx license if enabled
3169 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 }
3172
3173 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003174 status = voice_set_parameters(adev, parms);
3175 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003176 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 status = platform_set_parameters(adev->platform, parms);
3179 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003180 goto done;
3181
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3183 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003184 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3186 adev->bluetooth_nrec = true;
3187 else
3188 adev->bluetooth_nrec = false;
3189 }
3190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003191 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3192 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3194 adev->screen_off = false;
3195 else
3196 adev->screen_off = true;
3197 }
3198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003199 ret = str_parms_get_int(parms, "rotation", &val);
3200 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003201 bool reverse_speakers = false;
3202 switch(val) {
3203 // FIXME: note that the code below assumes that the speakers are in the correct placement
3204 // relative to the user when the device is rotated 90deg from its default rotation. This
3205 // assumption is device-specific, not platform-specific like this code.
3206 case 270:
3207 reverse_speakers = true;
3208 break;
3209 case 0:
3210 case 90:
3211 case 180:
3212 break;
3213 default:
3214 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003215 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003216 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003217 if (status == 0) {
3218 if (adev->speaker_lr_swap != reverse_speakers) {
3219 adev->speaker_lr_swap = reverse_speakers;
3220 // only update the selected device if there is active pcm playback
3221 struct audio_usecase *usecase;
3222 struct listnode *node;
3223 list_for_each(node, &adev->usecase_list) {
3224 usecase = node_to_item(node, struct audio_usecase, list);
3225 if (usecase->type == PCM_PLAYBACK) {
3226 select_devices(adev, usecase->id);
3227 break;
3228 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 }
3230 }
3231 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003232 }
3233
Mingming Yin514a8bc2014-07-29 15:22:21 -07003234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3235 if (ret >= 0) {
3236 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3237 adev->bt_wb_speech_enabled = true;
3238 else
3239 adev->bt_wb_speech_enabled = false;
3240 }
3241
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3243 if (ret >= 0) {
3244 val = atoi(value);
3245 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3246 ALOGV("cache new edid");
3247 platform_cache_edid(adev->platform);
3248 }
3249 }
3250
3251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3252 if (ret >= 0) {
3253 val = atoi(value);
3254 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3255 ALOGV("invalidate cached edid");
3256 platform_invalidate_edid(adev->platform);
3257 }
3258 }
3259
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003260 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003261
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003262done:
3263 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003264 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303265error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003266 ALOGV("%s: exit with code(%d)", __func__, status);
3267 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
3270static char* adev_get_parameters(const struct audio_hw_device *dev,
3271 const char *keys)
3272{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003273 struct audio_device *adev = (struct audio_device *)dev;
3274 struct str_parms *reply = str_parms_create();
3275 struct str_parms *query = str_parms_create_str(keys);
3276 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303277 char value[256] = {0};
3278 int ret = 0;
3279
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003280 if (!query || !reply) {
3281 ALOGE("adev_get_parameters: failed to create query or reply");
3282 return NULL;
3283 }
3284
Naresh Tannirud7205b62014-06-20 02:54:48 +05303285 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3286 sizeof(value));
3287 if (ret >=0) {
3288 int val = 1;
3289 pthread_mutex_lock(&adev->snd_card_status.lock);
3290 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3291 val = 0;
3292 pthread_mutex_unlock(&adev->snd_card_status.lock);
3293 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3294 goto exit;
3295 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003296
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003297 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003298 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003299 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003300 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303301 pthread_mutex_unlock(&adev->lock);
3302
Naresh Tannirud7205b62014-06-20 02:54:48 +05303303exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003304 str = str_parms_to_str(reply);
3305 str_parms_destroy(query);
3306 str_parms_destroy(reply);
3307
3308 ALOGV("%s: exit: returns - %s", __func__, str);
3309 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310}
3311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003312static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return 0;
3315}
3316
3317static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3318{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003319 int ret;
3320 struct audio_device *adev = (struct audio_device *)dev;
3321 pthread_mutex_lock(&adev->lock);
3322 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003323 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003324 pthread_mutex_unlock(&adev->lock);
3325 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326}
3327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003328static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3329 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330{
3331 return -ENOSYS;
3332}
3333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003334static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3335 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 return -ENOSYS;
3338}
3339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3341 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342{
3343 return -ENOSYS;
3344}
3345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003346static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3347 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348{
3349 return -ENOSYS;
3350}
3351
3352static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3353{
3354 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 pthread_mutex_lock(&adev->lock);
3357 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003360 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3361 voice_is_in_call(adev)) {
3362 voice_stop_call(adev);
3363 adev->current_call_output = NULL;
3364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 }
3366 pthread_mutex_unlock(&adev->lock);
3367 return 0;
3368}
3369
3370static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3371{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003372 int ret;
3373
3374 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003375 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003376 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3377 pthread_mutex_unlock(&adev->lock);
3378
3379 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380}
3381
3382static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3383{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003384 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 return 0;
3386}
3387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003388static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 const struct audio_config *config)
3390{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003391 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003393 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3394 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395}
3396
3397static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003398 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 audio_devices_t devices,
3400 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003401 struct audio_stream_in **stream_in,
3402 audio_input_flags_t flags __unused,
3403 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003404 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405{
3406 struct audio_device *adev = (struct audio_device *)dev;
3407 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003408 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003409 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003410 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 *stream_in = NULL;
3413 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3414 return -EINVAL;
3415
3416 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003417
3418 if (!in) {
3419 ALOGE("failed to allocate input stream");
3420 return -ENOMEM;
3421 }
3422
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303423 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003424 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3425 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003427 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 in->stream.common.get_sample_rate = in_get_sample_rate;
3430 in->stream.common.set_sample_rate = in_set_sample_rate;
3431 in->stream.common.get_buffer_size = in_get_buffer_size;
3432 in->stream.common.get_channels = in_get_channels;
3433 in->stream.common.get_format = in_get_format;
3434 in->stream.common.set_format = in_set_format;
3435 in->stream.common.standby = in_standby;
3436 in->stream.common.dump = in_dump;
3437 in->stream.common.set_parameters = in_set_parameters;
3438 in->stream.common.get_parameters = in_get_parameters;
3439 in->stream.common.add_audio_effect = in_add_audio_effect;
3440 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3441 in->stream.set_gain = in_set_gain;
3442 in->stream.read = in_read;
3443 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3444
3445 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003446 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->standby = 1;
3449 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003450 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
3452 /* Update config params with the requested sample rate and channels */
3453 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003454 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3455 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3456 is_low_latency = true;
3457#if LOW_LATENCY_CAPTURE_USE_CASE
3458 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3459#endif
3460 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003463 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003465 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303466 if (adev->mode != AUDIO_MODE_IN_CALL) {
3467 ret = -EINVAL;
3468 goto err_open;
3469 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003470 if (config->sample_rate == 0)
3471 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3472 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3473 config->sample_rate != 8000) {
3474 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3475 ret = -EINVAL;
3476 goto err_open;
3477 }
3478 if (config->format == AUDIO_FORMAT_DEFAULT)
3479 config->format = AUDIO_FORMAT_PCM_16_BIT;
3480 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3481 config->format = AUDIO_FORMAT_PCM_16_BIT;
3482 ret = -EINVAL;
3483 goto err_open;
3484 }
3485
3486 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3487 in->config = pcm_config_afe_proxy_record;
3488 in->config.channels = channel_count;
3489 in->config.rate = config->sample_rate;
3490 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003492 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003493 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3494 ret = -EINVAL;
3495 goto err_open;
3496 }
3497 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003498 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003499 }
Mingming Yine62d7842013-10-25 16:26:03 -07003500 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003501 audio_extn_compr_cap_format_supported(config->format) &&
3502 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003503 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003504 } else {
3505 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003506 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003507 buffer_size = get_input_buffer_size(config->sample_rate,
3508 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003509 channel_count,
3510 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003511 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003512 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3513 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3514 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3515 (in->config.rate == 8000 || in->config.rate == 16000) &&
3516 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3517 voice_extn_compress_voip_open_input_stream(in);
3518 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003521 /* This stream could be for sound trigger lab,
3522 get sound trigger pcm if present */
3523 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303524 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003527 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003528 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529
3530err_open:
3531 free(in);
3532 *stream_in = NULL;
3533 return ret;
3534}
3535
3536static void adev_close_input_stream(struct audio_hw_device *dev,
3537 struct audio_stream_in *stream)
3538{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003539 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003541 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303543 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003544
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303545 /* Disable echo reference while closing input stream */
3546 platform_set_echo_reference(adev->platform, false);
3547
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003548 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303549 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003550 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303551 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003552 if (ret != 0)
3553 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3554 __func__, ret);
3555 } else
3556 in_standby(&stream->common);
3557
Mingming Yin7b762e72015-03-04 13:47:32 -08003558 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003559 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003560 audio_extn_ssr_deinit();
3561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562
Mingming Yine62d7842013-10-25 16:26:03 -07003563 if(audio_extn_compr_cap_enabled() &&
3564 audio_extn_compr_cap_format_supported(in->config.format))
3565 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003566
3567 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 return;
3569}
3570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003571static int adev_dump(const audio_hw_device_t *device __unused,
3572 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573{
3574 return 0;
3575}
3576
3577static int adev_close(hw_device_t *device)
3578{
3579 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003580
3581 if (!adev)
3582 return 0;
3583
3584 pthread_mutex_lock(&adev_init_lock);
3585
3586 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003587 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003588 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003589 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003590 audio_route_free(adev->audio_route);
3591 free(adev->snd_dev_ref_cnt);
3592 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003593 free(device);
3594 adev = NULL;
3595 }
3596 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 return 0;
3598}
3599
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003600/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3601 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3602 * just that it _might_ work.
3603 */
3604static int period_size_is_plausible_for_low_latency(int period_size)
3605{
3606 switch (period_size) {
3607 case 160:
3608 case 240:
3609 case 320:
3610 case 480:
3611 return 1;
3612 default:
3613 return 0;
3614 }
3615}
3616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617static int adev_open(const hw_module_t *module, const char *name,
3618 hw_device_t **device)
3619{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003620 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003622 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3624
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003625 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003626 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003627 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003628 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003629 ALOGD("%s: returning existing instance of adev", __func__);
3630 ALOGD("%s: exit", __func__);
3631 pthread_mutex_unlock(&adev_init_lock);
3632 return 0;
3633 }
3634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 adev = calloc(1, sizeof(struct audio_device));
3636
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003637 if (!adev) {
3638 pthread_mutex_unlock(&adev_init_lock);
3639 return -ENOMEM;
3640 }
3641
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003642 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3645 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3646 adev->device.common.module = (struct hw_module_t *)module;
3647 adev->device.common.close = adev_close;
3648
3649 adev->device.init_check = adev_init_check;
3650 adev->device.set_voice_volume = adev_set_voice_volume;
3651 adev->device.set_master_volume = adev_set_master_volume;
3652 adev->device.get_master_volume = adev_get_master_volume;
3653 adev->device.set_master_mute = adev_set_master_mute;
3654 adev->device.get_master_mute = adev_get_master_mute;
3655 adev->device.set_mode = adev_set_mode;
3656 adev->device.set_mic_mute = adev_set_mic_mute;
3657 adev->device.get_mic_mute = adev_get_mic_mute;
3658 adev->device.set_parameters = adev_set_parameters;
3659 adev->device.get_parameters = adev_get_parameters;
3660 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3661 adev->device.open_output_stream = adev_open_output_stream;
3662 adev->device.close_output_stream = adev_close_output_stream;
3663 adev->device.open_input_stream = adev_open_input_stream;
3664 adev->device.close_input_stream = adev_close_input_stream;
3665 adev->device.dump = adev_dump;
3666
3667 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003669 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003670 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003673 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003674 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003675 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003676 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003677 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003678 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003679 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303680
3681 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3682 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003684 adev->platform = platform_init(adev);
3685 if (!adev->platform) {
3686 free(adev->snd_dev_ref_cnt);
3687 free(adev);
3688 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3689 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003690 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003691 return -EINVAL;
3692 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003693
Naresh Tanniru4c630392014-05-12 01:05:52 +05303694 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3695
Eric Laurentc4aef752013-09-12 17:45:53 -07003696 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3697 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3698 if (adev->visualizer_lib == NULL) {
3699 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3700 } else {
3701 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3702 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003703 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003704 "visualizer_hal_start_output");
3705 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003706 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003707 "visualizer_hal_stop_output");
3708 }
3709 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003710 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003711 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003712
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003713 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3714 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3715 if (adev->offload_effects_lib == NULL) {
3716 ALOGE("%s: DLOPEN failed for %s", __func__,
3717 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3718 } else {
3719 ALOGV("%s: DLOPEN successful for %s", __func__,
3720 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3721 adev->offload_effects_start_output =
3722 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3723 "offload_effects_bundle_hal_start_output");
3724 adev->offload_effects_stop_output =
3725 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3726 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003727 adev->offload_effects_set_hpx_state =
3728 (int (*)(bool))dlsym(adev->offload_effects_lib,
3729 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003730 }
3731 }
3732
Mingming Yin514a8bc2014-07-29 15:22:21 -07003733 adev->bt_wb_speech_enabled = false;
3734
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003735 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 *device = &adev->device.common;
3737
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003738 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3739 &adev->streams_output_cfg_list);
3740
Kiran Kandi910e1862013-10-29 13:29:42 -07003741 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003742
3743 char value[PROPERTY_VALUE_MAX];
3744 int trial;
3745 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3746 trial = atoi(value);
3747 if (period_size_is_plausible_for_low_latency(trial)) {
3748 pcm_config_low_latency.period_size = trial;
3749 pcm_config_low_latency.start_threshold = trial / 4;
3750 pcm_config_low_latency.avail_min = trial / 4;
3751 configured_low_latency_capture_period_size = trial;
3752 }
3753 }
3754 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3755 trial = atoi(value);
3756 if (period_size_is_plausible_for_low_latency(trial)) {
3757 configured_low_latency_capture_period_size = trial;
3758 }
3759 }
3760
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003761 pthread_mutex_unlock(&adev_init_lock);
3762
Eric Laurent994a6932013-07-17 11:51:42 -07003763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 return 0;
3765}
3766
3767static struct hw_module_methods_t hal_module_methods = {
3768 .open = adev_open,
3769};
3770
3771struct audio_module HAL_MODULE_INFO_SYM = {
3772 .common = {
3773 .tag = HARDWARE_MODULE_TAG,
3774 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3775 .hal_api_version = HARDWARE_HAL_API_VERSION,
3776 .id = AUDIO_HARDWARE_MODULE_ID,
3777 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003778 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 .methods = &hal_module_methods,
3780 },
3781};