blob: 4bc6b59f011e971c08c64193128fc2ad51a55687 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
vivek mehtaa76401a2015-04-24 14:12:15 -0700255__attribute__ ((visibility ("default")))
256bool audio_hw_send_gain_dep_calibration(int level) {
257 bool ret_val = false;
258 ALOGV("%s: called ... ", __func__);
259
260 pthread_mutex_lock(&adev_init_lock);
261
262 if (adev != NULL && adev->platform != NULL) {
263 pthread_mutex_lock(&adev->lock);
264 ret_val = platform_send_gain_dep_cal(adev->platform, level);
265 pthread_mutex_unlock(&adev->lock);
266 } else {
267 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
268 }
269
270 pthread_mutex_unlock(&adev_init_lock);
271
272 return ret_val;
273}
274
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800275static int check_and_set_gapless_mode(struct audio_device *adev) {
276
277
278 char value[PROPERTY_VALUE_MAX] = {0};
279 bool gapless_enabled = false;
280 const char *mixer_ctl_name = "Compress Gapless Playback";
281 struct mixer_ctl *ctl;
282
283 ALOGV("%s:", __func__);
284 property_get("audio.offload.gapless.enabled", value, NULL);
285 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
286
287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
288 if (!ctl) {
289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
290 __func__, mixer_ctl_name);
291 return -EINVAL;
292 }
293
294 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
295 ALOGE("%s: Could not set gapless mode %d",
296 __func__, gapless_enabled);
297 return -EINVAL;
298 }
299 return 0;
300}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700302static bool is_supported_format(audio_format_t format)
303{
Eric Laurent86e17132013-09-12 17:49:30 -0700304 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 format == AUDIO_FORMAT_AAC_LC ||
306 format == AUDIO_FORMAT_AAC_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800310 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530311 format == AUDIO_FORMAT_ALAC ||
312 format == AUDIO_FORMAT_APE ||
313 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_WMA ||
315 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800316 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317
318 return false;
319}
320
321static int get_snd_codec_id(audio_format_t format)
322{
323 int id = 0;
324
Ashish Jainf9b78162014-08-25 20:36:25 +0530325 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700326 case AUDIO_FORMAT_MP3:
327 id = SND_AUDIOCODEC_MP3;
328 break;
329 case AUDIO_FORMAT_AAC:
330 id = SND_AUDIOCODEC_AAC;
331 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800333 id = SND_AUDIOCODEC_PCM;
334 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700335 case AUDIO_FORMAT_FLAC:
336 id = SND_AUDIOCODEC_FLAC;
337 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530338 case AUDIO_FORMAT_ALAC:
339 id = SND_AUDIOCODEC_ALAC;
340 break;
341 case AUDIO_FORMAT_APE:
342 id = SND_AUDIOCODEC_APE;
343 break;
344 case AUDIO_FORMAT_VORBIS:
345 id = SND_AUDIOCODEC_VORBIS;
346 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800347 case AUDIO_FORMAT_WMA:
348 id = SND_AUDIOCODEC_WMA;
349 break;
350 case AUDIO_FORMAT_WMA_PRO:
351 id = SND_AUDIOCODEC_WMA_PRO;
352 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700353 default:
Mingming Yin90310102013-11-13 16:57:00 -0800354 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700355 }
356
357 return id;
358}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800359
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530360int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530361{
362 int snd_scard_state;
363
364 if (!adev)
365 return SND_CARD_STATE_OFFLINE;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 snd_scard_state = adev->snd_card_status.state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return snd_scard_state;
372}
373
374static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
375{
376 if (!adev)
377 return -ENOSYS;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700380 if (adev->snd_card_status.state != snd_scard_state) {
381 adev->snd_card_status.state = snd_scard_state;
382 platform_snd_card_update(adev->platform, snd_scard_state);
383 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530384 pthread_mutex_unlock(&adev->snd_card_status.lock);
385
386 return 0;
387}
388
Avinash Vaish71a8b972014-07-24 15:36:33 +0530389static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
390 struct audio_usecase *uc_info)
391{
392 struct listnode *node;
393 struct audio_usecase *usecase;
394
395 if (uc_info == NULL)
396 return -EINVAL;
397
398 /* Re-route all voice usecases on the shared backend other than the
399 specified usecase to new snd devices */
400 list_for_each(node, &adev->usecase_list) {
401 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800402 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530403 enable_audio_route(adev, usecase);
404 }
405 return 0;
406}
407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700408int pcm_ioctl(struct pcm *pcm, int request, ...)
409{
410 va_list ap;
411 void * arg;
412 int pcm_fd = *(int*)pcm;
413
414 va_start(ap, request);
415 arg = va_arg(ap, void *);
416 va_end(ap);
417
418 return ioctl(pcm_fd, request, arg);
419}
420
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700421int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700422 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700425 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426
427 if (usecase == NULL)
428 return -EINVAL;
429
430 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
431
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800432 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800434 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800437#ifdef DS1_DOLBY_DAP_ENABLED
438 audio_extn_dolby_set_dmid(adev);
439 audio_extn_dolby_set_endpoint(adev);
440#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700441 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530443 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700444 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700445 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700447 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700448 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
449 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 ALOGV("%s: exit", __func__);
451 return 0;
452}
453
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700454int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700455 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700458 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530460 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461 return -EINVAL;
462
463 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 if (usecase->type == PCM_CAPTURE)
465 snd_device = usecase->in_snd_device;
466 else
467 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700469 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700470 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
471 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700472 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530473 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700478int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
482
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800483 if (snd_device < SND_DEVICE_MIN ||
484 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800485 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800486 return -EINVAL;
487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
489 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700490
491 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
492 ALOGE("%s: Invalid sound device returned", __func__);
493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700496 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 return 0;
499 }
500
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700501 if (audio_extn_spkr_prot_is_enabled())
502 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 /* start usb playback thread */
504 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
505 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
506 audio_extn_usb_start_playback(adev);
507
508 /* start usb capture thread */
509 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
510 audio_extn_usb_start_capture(adev);
511
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800512 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
513 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700514 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700515 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
516 adev->snd_dev_ref_cnt[snd_device]--;
517 return -EINVAL;
518 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200519 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800520 if (audio_extn_spkr_prot_start_processing(snd_device)) {
521 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200522 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 return -EINVAL;
524 }
525 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
527 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700528 /* due to the possibility of calibration overwrite between listen
529 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700530 audio_extn_sound_trigger_update_device_status(snd_device,
531 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530532 audio_extn_listen_update_device_status(snd_device,
533 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700534 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700535 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 return -EINVAL;
541 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300542 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700543 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545 return 0;
546}
547
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700548int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700549 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
552
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800553 if (snd_device < SND_DEVICE_MIN ||
554 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800555 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800556 return -EINVAL;
557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700558 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
559 ALOGE("%s: device ref cnt is already 0", __func__);
560 return -EINVAL;
561 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700564
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700571 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800573 /* exit usb play back thread */
574 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
575 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
576 audio_extn_usb_stop_playback();
577
578 /* exit usb capture thread */
579 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700580 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800581
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
583 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700584 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700585 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300586 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700587 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300588 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700589
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200590 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700591 audio_extn_sound_trigger_update_device_status(snd_device,
592 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530593 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800594 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 return 0;
598}
599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600static void check_usecases_codec_backend(struct audio_device *adev,
601 struct audio_usecase *uc_info,
602 snd_device_t snd_device)
603{
604 struct listnode *node;
605 struct audio_usecase *usecase;
606 bool switch_device[AUDIO_USECASE_MAX];
607 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800608 int backend_idx = DEFAULT_CODEC_BACKEND;
609 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
611 /*
612 * This function is to make sure that all the usecases that are active on
613 * the hardware codec backend are always routed to any one device that is
614 * handled by the hardware codec.
615 * For example, if low-latency and deep-buffer usecases are currently active
616 * on speaker and out_set_parameters(headset) is received on low-latency
617 * output, then we have to make sure deep-buffer is also switched to headset,
618 * because of the limitation that both the devices cannot be enabled
619 * at the same time as they share the same backend.
620 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700621 /*
622 * This call is to check if we need to force routing for a particular stream
623 * If there is a backend configuration change for the device when a
624 * new stream starts, then ADM needs to be closed and re-opened with the new
625 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800626 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800628 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
629 snd_device);
630 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800632 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800633 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 for (i = 0; i < AUDIO_USECASE_MAX; i++)
635 switch_device[i] = false;
636
637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800639
640 if (usecase == uc_info)
641 continue;
642 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
643 ALOGV("%s: backend_idx: %d,"
644 "usecase_backend_idx: %d, curr device: %s, usecase device:"
645 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530646 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800647
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800648 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700649 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800650 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
651 usecase_backend_idx == backend_idx) {
652 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
653 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700654 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700655 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 switch_device[usecase->id] = true;
657 num_uc_to_switch++;
658 }
659 }
660
661 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700662 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530664 /* Make sure the previous devices to be disabled first and then enable the
665 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 list_for_each(node, &adev->usecase_list) {
667 usecase = node_to_item(node, struct audio_usecase, list);
668 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700673 list_for_each(node, &adev->usecase_list) {
674 usecase = node_to_item(node, struct audio_usecase, list);
675 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700676 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700677 }
678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 /* Re-route all the usecases on the shared backend other than the
681 specified usecase to new snd devices */
682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
684 /* Update the out_snd_device only before enabling the audio route */
685 if (switch_device[usecase->id] ) {
686 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800687 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530688 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 }
690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 }
692}
693
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700694static void check_and_route_capture_usecases(struct audio_device *adev,
695 struct audio_usecase *uc_info,
696 snd_device_t snd_device)
697{
698 struct listnode *node;
699 struct audio_usecase *usecase;
700 bool switch_device[AUDIO_USECASE_MAX];
701 int i, num_uc_to_switch = 0;
702
703 /*
704 * This function is to make sure that all the active capture usecases
705 * are always routed to the same input sound device.
706 * For example, if audio-record and voice-call usecases are currently
707 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
708 * is received for voice call then we have to make sure that audio-record
709 * usecase is also switched to earpiece i.e. voice-dmic-ef,
710 * because of the limitation that two devices cannot be enabled
711 * at the same time if they share the same backend.
712 */
713 for (i = 0; i < AUDIO_USECASE_MAX; i++)
714 switch_device[i] = false;
715
716 list_for_each(node, &adev->usecase_list) {
717 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800718 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700720 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530721 (usecase->devices & AUDIO_DEVICE_OUT_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 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
897 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700898 select_devices(adev, adev->active_input->usecase);
899 }
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 } else if (usecase->type == PCM_CAPTURE) {
902 usecase->devices = usecase->stream.in->device;
903 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700904 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700905 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530906 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
907 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
908 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
909 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700910 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800911 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700912 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
913 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700914 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700915 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700916 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 }
918 }
919
920 if (out_snd_device == usecase->out_snd_device &&
921 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 return 0;
923 }
924
sangwoobc677242013-08-08 16:53:43 +0900925 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700926 out_snd_device, platform_get_snd_device_name(out_snd_device),
927 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 /*
930 * Limitation: While in call, to do a device switch we need to disable
931 * and enable both RX and TX devices though one of them is same as current
932 * device.
933 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700934 if ((usecase->type == VOICE_CALL) &&
935 (usecase->in_snd_device != SND_DEVICE_NONE) &&
936 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700937 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700938 /* Disable sidetone only if voice call already exists */
939 if (voice_is_call_state_active(adev))
940 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800941 }
942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 /* Disable current sound devices */
944 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700945 disable_audio_route(adev, usecase);
946 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947 }
948
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700949 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700950 disable_audio_route(adev, usecase);
951 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800954 /* Applicable only on the targets that has external modem.
955 * New device information should be sent to modem before enabling
956 * the devices to reduce in-call device switch time.
957 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700958 if ((usecase->type == VOICE_CALL) &&
959 (usecase->in_snd_device != SND_DEVICE_NONE) &&
960 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800961 status = platform_switch_voice_call_enable_device_config(adev->platform,
962 out_snd_device,
963 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700964 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800965
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 /* Enable new sound devices */
967 if (out_snd_device != SND_DEVICE_NONE) {
968 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
969 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700970 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 }
972
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700973 if (in_snd_device != SND_DEVICE_NONE) {
974 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700975 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977
Avinash Vaish71a8b972014-07-24 15:36:33 +0530978 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700979 status = platform_switch_voice_call_device_post(adev->platform,
980 out_snd_device,
981 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530982 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700983 /* Enable sidetone only if voice call already exists */
984 if (voice_is_call_state_active(adev))
985 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530986 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800987
sangwoo170731f2013-06-08 15:36:36 +0900988 usecase->in_snd_device = in_snd_device;
989 usecase->out_snd_device = out_snd_device;
990
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530991 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700992 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530993 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700994 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530995 usecase->stream.out->flags,
996 usecase->stream.out->format,
997 usecase->stream.out->sample_rate,
998 usecase->stream.out->bit_width,
999 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001002
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001003 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001004
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001005 /* Applicable only on the targets that has external modem.
1006 * Enable device command should be sent to modem only after
1007 * enabling voice call mixer controls
1008 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001009 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001010 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1011 out_snd_device,
1012 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301013 ALOGD("%s: done",__func__);
1014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 return status;
1016}
1017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018static int stop_input_stream(struct stream_in *in)
1019{
1020 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 struct audio_usecase *uc_info;
1022 struct audio_device *adev = in->dev;
1023
Eric Laurentc8400632013-02-14 19:04:54 -08001024 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Eric Laurent994a6932013-07-17 11:51:42 -07001026 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 uc_info = get_usecase_from_list(adev, in->usecase);
1029 if (uc_info == NULL) {
1030 ALOGE("%s: Could not find the usecase (%d) in the list",
1031 __func__, in->usecase);
1032 return -EINVAL;
1033 }
1034
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001035 /* Close in-call recording streams */
1036 voice_check_and_stop_incall_rec_usecase(adev, in);
1037
Eric Laurent150dbfe2013-02-27 14:31:02 -08001038 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001039 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040
1041 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001044 list_remove(&uc_info->list);
1045 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 return ret;
1049}
1050
1051int start_input_stream(struct stream_in *in)
1052{
1053 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001054 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 struct audio_usecase *uc_info;
1056 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301057 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Mingming Yine62d7842013-10-25 16:26:03 -07001059 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301060 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1061 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001062
Naresh Tanniru80659832014-06-04 18:17:56 +05301063
1064 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301065 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301066 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301067 goto error_config;
1068 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301069
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001070 /* Check if source matches incall recording usecase criteria */
1071 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1072 if (ret)
1073 goto error_config;
1074 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001075 ALOGD("%s: Updated usecase(%d: %s)",
1076 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001077
Eric Laurentb23d5282013-05-14 15:27:20 -07001078 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079 if (in->pcm_device_id < 0) {
1080 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1081 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001082 ret = -EINVAL;
1083 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085
1086 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001088
1089 if (!uc_info) {
1090 ret = -ENOMEM;
1091 goto error_config;
1092 }
1093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 uc_info->id = in->usecase;
1095 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001096 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 uc_info->devices = in->device;
1098 uc_info->in_snd_device = SND_DEVICE_NONE;
1099 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001101 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301102 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104
Eric Laurentc8400632013-02-14 19:04:54 -08001105 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001106 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1107
1108 unsigned int flags = PCM_IN;
1109 unsigned int pcm_open_retry_count = 0;
1110
1111 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1112 flags |= PCM_MMAP | PCM_NOIRQ;
1113 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1114 }
1115
1116 while (1) {
1117 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1118 flags, &in->config);
1119 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1120 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1121 if (in->pcm != NULL) {
1122 pcm_close(in->pcm);
1123 in->pcm = NULL;
1124 }
1125 if (pcm_open_retry_count-- == 0) {
1126 ret = -EIO;
1127 goto error_open;
1128 }
1129 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1130 continue;
1131 }
1132 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301134 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301135
Eric Laurent994a6932013-07-17 11:51:42 -07001136 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001137 return ret;
1138
1139error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301141 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001142
1143error_config:
1144 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001146
1147 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148}
1149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001150/* must be called with out->lock locked */
1151static int send_offload_cmd_l(struct stream_out* out, int command)
1152{
1153 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1154
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001155 if (!cmd) {
1156 ALOGE("failed to allocate mem for command 0x%x", command);
1157 return -ENOMEM;
1158 }
1159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001160 ALOGVV("%s %d", __func__, command);
1161
1162 cmd->cmd = command;
1163 list_add_tail(&out->offload_cmd_list, &cmd->node);
1164 pthread_cond_signal(&out->offload_cond);
1165 return 0;
1166}
1167
1168/* must be called iwth out->lock locked */
1169static void stop_compressed_output_l(struct stream_out *out)
1170{
1171 out->offload_state = OFFLOAD_STATE_IDLE;
1172 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001173 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001174 if (out->compr != NULL) {
1175 compress_stop(out->compr);
1176 while (out->offload_thread_blocked) {
1177 pthread_cond_wait(&out->cond, &out->lock);
1178 }
1179 }
1180}
1181
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001182bool is_offload_usecase(audio_usecase_t uc_id)
1183{
1184 unsigned int i;
1185 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1186 if (uc_id == offload_usecases[i])
1187 return true;
1188 }
1189 return false;
1190}
1191
1192static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1193{
1194 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1195 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1196 char value[PROPERTY_VALUE_MAX] = {0};
1197
1198 property_get("audio.offload.multiple.enabled", value, NULL);
1199 if (!(atoi(value) || !strncmp("true", value, 4)))
1200 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1201
1202 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1203 for (i = 0; i < num_usecase; i++) {
1204 if (!(adev->offload_usecases_state & (0x1<<i))) {
1205 adev->offload_usecases_state |= 0x1 << i;
1206 ret = offload_usecases[i];
1207 break;
1208 }
1209 }
1210 ALOGV("%s: offload usecase is %d", __func__, ret);
1211 return ret;
1212}
1213
1214static void free_offload_usecase(struct audio_device *adev,
1215 audio_usecase_t uc_id)
1216{
1217 unsigned int i;
1218 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1219 if (offload_usecases[i] == uc_id) {
1220 adev->offload_usecases_state &= ~(0x1<<i);
1221 break;
1222 }
1223 }
1224 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1225}
1226
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001227static void *offload_thread_loop(void *context)
1228{
1229 struct stream_out *out = (struct stream_out *) context;
1230 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001231 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1234 set_sched_policy(0, SP_FOREGROUND);
1235 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1236
1237 ALOGV("%s", __func__);
1238 pthread_mutex_lock(&out->lock);
1239 for (;;) {
1240 struct offload_cmd *cmd = NULL;
1241 stream_callback_event_t event;
1242 bool send_callback = false;
1243
1244 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1245 __func__, list_empty(&out->offload_cmd_list),
1246 out->offload_state);
1247 if (list_empty(&out->offload_cmd_list)) {
1248 ALOGV("%s SLEEPING", __func__);
1249 pthread_cond_wait(&out->offload_cond, &out->lock);
1250 ALOGV("%s RUNNING", __func__);
1251 continue;
1252 }
1253
1254 item = list_head(&out->offload_cmd_list);
1255 cmd = node_to_item(item, struct offload_cmd, node);
1256 list_remove(item);
1257
1258 ALOGVV("%s STATE %d CMD %d out->compr %p",
1259 __func__, out->offload_state, cmd->cmd, out->compr);
1260
1261 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1262 free(cmd);
1263 break;
1264 }
1265
1266 if (out->compr == NULL) {
1267 ALOGE("%s: Compress handle is NULL", __func__);
1268 pthread_cond_signal(&out->cond);
1269 continue;
1270 }
1271 out->offload_thread_blocked = true;
1272 pthread_mutex_unlock(&out->lock);
1273 send_callback = false;
1274 switch(cmd->cmd) {
1275 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001276 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001278 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001279 send_callback = true;
1280 event = STREAM_CBK_EVENT_WRITE_READY;
1281 break;
1282 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001283 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301284 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301286 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001287 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301288 if (ret < 0)
1289 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301290 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301291 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001292 compress_drain(out->compr);
1293 else
1294 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301295 if (ret != -ENETRESET) {
1296 send_callback = true;
1297 event = STREAM_CBK_EVENT_DRAIN_READY;
1298 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1299 } else
1300 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 break;
1302 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001303 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001305 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 send_callback = true;
1307 event = STREAM_CBK_EVENT_DRAIN_READY;
1308 break;
1309 default:
1310 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1311 break;
1312 }
1313 pthread_mutex_lock(&out->lock);
1314 out->offload_thread_blocked = false;
1315 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001316 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001317 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001319 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 free(cmd);
1321 }
1322
1323 pthread_cond_signal(&out->cond);
1324 while (!list_empty(&out->offload_cmd_list)) {
1325 item = list_head(&out->offload_cmd_list);
1326 list_remove(item);
1327 free(node_to_item(item, struct offload_cmd, node));
1328 }
1329 pthread_mutex_unlock(&out->lock);
1330
1331 return NULL;
1332}
1333
1334static int create_offload_callback_thread(struct stream_out *out)
1335{
1336 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1337 list_init(&out->offload_cmd_list);
1338 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1339 offload_thread_loop, out);
1340 return 0;
1341}
1342
1343static int destroy_offload_callback_thread(struct stream_out *out)
1344{
1345 pthread_mutex_lock(&out->lock);
1346 stop_compressed_output_l(out);
1347 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1348
1349 pthread_mutex_unlock(&out->lock);
1350 pthread_join(out->offload_thread, (void **) NULL);
1351 pthread_cond_destroy(&out->offload_cond);
1352
1353 return 0;
1354}
1355
Eric Laurent07eeafd2013-10-06 12:52:49 -07001356static bool allow_hdmi_channel_config(struct audio_device *adev)
1357{
1358 struct listnode *node;
1359 struct audio_usecase *usecase;
1360 bool ret = true;
1361
1362 list_for_each(node, &adev->usecase_list) {
1363 usecase = node_to_item(node, struct audio_usecase, list);
1364 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1365 /*
1366 * If voice call is already existing, do not proceed further to avoid
1367 * disabling/enabling both RX and TX devices, CSD calls, etc.
1368 * Once the voice call done, the HDMI channels can be configured to
1369 * max channels of remaining use cases.
1370 */
1371 if (usecase->id == USECASE_VOICE_CALL) {
1372 ALOGD("%s: voice call is active, no change in HDMI channels",
1373 __func__);
1374 ret = false;
1375 break;
1376 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1377 ALOGD("%s: multi channel playback is active, "
1378 "no change in HDMI channels", __func__);
1379 ret = false;
1380 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001381 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001382 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001383 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1384 ", no change in HDMI channels", __func__,
1385 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001386 ret = false;
1387 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 }
1389 }
1390 }
1391 return ret;
1392}
1393
1394static int check_and_set_hdmi_channels(struct audio_device *adev,
1395 unsigned int channels)
1396{
1397 struct listnode *node;
1398 struct audio_usecase *usecase;
1399
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001400 unsigned int supported_channels = platform_edid_get_max_channels(
1401 adev->platform);
1402 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403 /* Check if change in HDMI channel config is allowed */
1404 if (!allow_hdmi_channel_config(adev))
1405 return 0;
1406
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001407 if (channels > supported_channels)
1408 channels = supported_channels;
1409
Eric Laurent07eeafd2013-10-06 12:52:49 -07001410 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001411 ALOGD("%s: Requested channels are same as current channels(%d)",
1412 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 return 0;
1414 }
1415
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001416 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001418 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 adev->cur_hdmi_channels = channels;
1420
1421 /*
1422 * Deroute all the playback streams routed to HDMI so that
1423 * the back end is deactivated. Note that backend will not
1424 * be deactivated if any one stream is connected to it.
1425 */
1426 list_for_each(node, &adev->usecase_list) {
1427 usecase = node_to_item(node, struct audio_usecase, list);
1428 if (usecase->type == PCM_PLAYBACK &&
1429 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001430 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 }
1432 }
1433
1434 /*
1435 * Enable all the streams disabled above. Now the HDMI backend
1436 * will be activated with new channel configuration
1437 */
1438 list_for_each(node, &adev->usecase_list) {
1439 usecase = node_to_item(node, struct audio_usecase, list);
1440 if (usecase->type == PCM_PLAYBACK &&
1441 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001442 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001443 }
1444 }
1445
1446 return 0;
1447}
1448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449static int stop_output_stream(struct stream_out *out)
1450{
1451 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 struct audio_usecase *uc_info;
1453 struct audio_device *adev = out->dev;
1454
Eric Laurent994a6932013-07-17 11:51:42 -07001455 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 uc_info = get_usecase_from_list(adev, out->usecase);
1458 if (uc_info == NULL) {
1459 ALOGE("%s: Could not find the usecase (%d) in the list",
1460 __func__, out->usecase);
1461 return -EINVAL;
1462 }
1463
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001464 if (is_offload_usecase(out->usecase) &&
1465 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001466 if (adev->visualizer_stop_output != NULL)
1467 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001468
1469 audio_extn_dts_remove_state_notifier_node(out->usecase);
1470
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001471 if (adev->offload_effects_stop_output != NULL)
1472 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1473 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001474
Eric Laurent150dbfe2013-02-27 14:31:02 -08001475 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001476 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477
1478 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001479 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001481 list_remove(&uc_info->list);
1482 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001484 if (is_offload_usecase(out->usecase) &&
1485 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1486 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1487 ALOGV("Disable passthrough , reset mixer to pcm");
1488 /* NO_PASSTHROUGH */
1489 out->compr_config.codec->compr_passthr = 0;
1490 audio_extn_dolby_set_hdmi_config(adev, out);
1491 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1492 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001493 /* Must be called after removing the usecase from list */
1494 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1495 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1496
Eric Laurent994a6932013-07-17 11:51:42 -07001497 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 return ret;
1499}
1500
1501int start_output_stream(struct stream_out *out)
1502{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001504 int sink_channels = 0;
1505 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 struct audio_usecase *uc_info;
1507 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301508 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001510 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1511 ret = -EINVAL;
1512 goto error_config;
1513 }
1514
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301515 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1516 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1517 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301518
Naresh Tanniru80659832014-06-04 18:17:56 +05301519 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301520 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301521 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301522 goto error_config;
1523 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301524
Eric Laurentb23d5282013-05-14 15:27:20 -07001525 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 if (out->pcm_device_id < 0) {
1527 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1528 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001529 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001530 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 }
1532
1533 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001534
1535 if (!uc_info) {
1536 ret = -ENOMEM;
1537 goto error_config;
1538 }
1539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 uc_info->id = out->usecase;
1541 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001542 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 uc_info->devices = out->devices;
1544 uc_info->in_snd_device = SND_DEVICE_NONE;
1545 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001547 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001548 if (is_offload_usecase(out->usecase)) {
1549 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001550 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1551 }
1552 }
Mingming Yin9c041392014-05-01 15:37:31 -07001553 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1554 if (!strncmp("true", prop_value, 4)) {
1555 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001556 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1557 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001558 check_and_set_hdmi_channels(adev, sink_channels);
1559 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 if (is_offload_usecase(out->usecase)) {
1561 unsigned int ch_count = out->compr_config.codec->ch_in;
1562 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1563 /* backend channel config for passthrough stream is stereo */
1564 ch_count = 2;
1565 check_and_set_hdmi_channels(adev, ch_count);
1566 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001567 check_and_set_hdmi_channels(adev, out->config.channels);
1568 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001569 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001570 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001571 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 select_devices(adev, out->usecase);
1574
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1576 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001577 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001578 unsigned int flags = PCM_OUT;
1579 unsigned int pcm_open_retry_count = 0;
1580 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1581 flags |= PCM_MMAP | PCM_NOIRQ;
1582 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1583 } else
1584 flags |= PCM_MONOTONIC;
1585
1586 while (1) {
1587 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1588 flags, &out->config);
1589 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1590 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1591 if (out->pcm != NULL) {
1592 pcm_close(out->pcm);
1593 out->pcm = NULL;
1594 }
1595 if (pcm_open_retry_count-- == 0) {
1596 ret = -EIO;
1597 goto error_open;
1598 }
1599 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1600 continue;
1601 }
1602 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001604 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1605 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001607 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1608 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001610 out->compr = compress_open(adev->snd_card,
1611 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 COMPRESS_IN, &out->compr_config);
1613 if (out->compr && !is_compress_ready(out->compr)) {
1614 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1615 compress_close(out->compr);
1616 out->compr = NULL;
1617 ret = -EIO;
1618 goto error_open;
1619 }
1620 if (out->offload_callback)
1621 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001622
Fred Oh3f43e742015-03-04 18:42:34 -08001623 /* Since small bufs uses blocking writes, a write will be blocked
1624 for the default max poll time (20s) in the event of an SSR.
1625 Reduce the poll time to observe and deal with SSR faster.
1626 */
1627 if (out->use_small_bufs) {
1628 compress_set_max_poll_wait(out->compr, 1000);
1629 }
1630
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001631 audio_extn_dts_create_state_notifier_node(out->usecase);
1632 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1633 popcount(out->channel_mask),
1634 out->playback_started);
1635
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001636#ifdef DS1_DOLBY_DDP_ENABLED
1637 if (audio_extn_is_dolby_format(out->format))
1638 audio_extn_dolby_send_ddp_endp_params(adev);
1639#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001640 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1641 if (adev->visualizer_start_output != NULL)
1642 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1643 if (adev->offload_effects_start_output != NULL)
1644 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001645 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 }
Eric Laurent994a6932013-07-17 11:51:42 -07001648 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001650error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001652error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001653 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654}
1655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656static int check_input_parameters(uint32_t sample_rate,
1657 audio_format_t format,
1658 int channel_count)
1659{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001660 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001662 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001663 !voice_extn_compress_voip_is_format_supported(format) &&
1664 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001665
1666 switch (channel_count) {
1667 case 1:
1668 case 2:
1669 case 6:
1670 break;
1671 default:
1672 ret = -EINVAL;
1673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
1675 switch (sample_rate) {
1676 case 8000:
1677 case 11025:
1678 case 12000:
1679 case 16000:
1680 case 22050:
1681 case 24000:
1682 case 32000:
1683 case 44100:
1684 case 48000:
1685 break;
1686 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001687 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 }
1689
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001690 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691}
1692
1693static size_t get_input_buffer_size(uint32_t sample_rate,
1694 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001695 int channel_count,
1696 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697{
1698 size_t size = 0;
1699
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001700 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1701 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001703 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001704 if (is_low_latency)
1705 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001706 /* ToDo: should use frame_size computed based on the format and
1707 channel_count here. */
1708 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001710 /* make sure the size is multiple of 32 bytes
1711 * At 48 kHz mono 16-bit PCM:
1712 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1713 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1714 */
1715 size += 0x1f;
1716 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001717
1718 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719}
1720
1721static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1722{
1723 struct stream_out *out = (struct stream_out *)stream;
1724
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726}
1727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001728static int out_set_sample_rate(struct audio_stream *stream __unused,
1729 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730{
1731 return -ENOSYS;
1732}
1733
1734static size_t out_get_buffer_size(const struct audio_stream *stream)
1735{
1736 struct stream_out *out = (struct stream_out *)stream;
1737
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001738 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001740 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1741 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001743 return out->config.period_size *
1744 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745}
1746
1747static uint32_t out_get_channels(const struct audio_stream *stream)
1748{
1749 struct stream_out *out = (struct stream_out *)stream;
1750
1751 return out->channel_mask;
1752}
1753
1754static audio_format_t out_get_format(const struct audio_stream *stream)
1755{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 struct stream_out *out = (struct stream_out *)stream;
1757
1758 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759}
1760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001761static int out_set_format(struct audio_stream *stream __unused,
1762 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763{
1764 return -ENOSYS;
1765}
1766
1767static int out_standby(struct audio_stream *stream)
1768{
1769 struct stream_out *out = (struct stream_out *)stream;
1770 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301772 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1773 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001774 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1775 /* Ignore standby in case of voip call because the voip output
1776 * stream is closed in adev_close_output_stream()
1777 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301778 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 return 0;
1780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001784 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001786 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001787 if (out->pcm) {
1788 pcm_close(out->pcm);
1789 out->pcm = NULL;
1790 }
1791 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001792 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001794 out->gapless_mdata.encoder_delay = 0;
1795 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 if (out->compr != NULL) {
1797 compress_close(out->compr);
1798 out->compr = NULL;
1799 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001802 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 }
1804 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001805 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 return 0;
1807}
1808
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001809static int out_dump(const struct audio_stream *stream __unused,
1810 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811{
1812 return 0;
1813}
1814
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001815static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1816{
1817 int ret = 0;
1818 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001819 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001820
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001822 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 return -EINVAL;
1824 }
1825
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001826 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1827 if (ret >= 0) {
1828 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1829 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1830 ALOGV("ADTS format is set in offload mode");
1831 }
1832 out->send_new_metadata = 1;
1833 }
1834
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301835 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001836
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1838 if(ret >= 0)
1839 is_meta_data_params = true;
1840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301841 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001842 is_meta_data_params = true;
1843 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301844 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001845 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001846 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1847 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001848 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301849 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1852 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001853 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301854 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 }
1856
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001857 if(!is_meta_data_params) {
1858 ALOGV("%s: Not gapless meta data params", __func__);
1859 return 0;
1860 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 out->send_new_metadata = 1;
1862 ALOGV("%s new encoder delay %u and padding %u", __func__,
1863 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1864
1865 return 0;
1866}
1867
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001868static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1869{
1870 return out == adev->primary_output || out == adev->voice_tx_output;
1871}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1874{
1875 struct stream_out *out = (struct stream_out *)stream;
1876 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001877 struct audio_usecase *usecase;
1878 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 struct str_parms *parms;
1880 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001881 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001882 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883
sangwoobc677242013-08-08 16:53:43 +09001884 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301887 if (!parms)
1888 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001889 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1890 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001893 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301896 * When HDMI cable is unplugged/usb hs is disconnected the
1897 * music playback is paused and the policy manager sends routing=0
1898 * But the audioflingercontinues to write data until standby time
1899 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 * Avoid this by routing audio to speaker until standby.
1901 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301902 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1903 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001905 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1906 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 }
1908
1909 /*
1910 * select_devices() call below switches all the usecases on the same
1911 * backend to the new device. Refer to check_usecases_codec_backend() in
1912 * the select_devices(). But how do we undo this?
1913 *
1914 * For example, music playback is active on headset (deep-buffer usecase)
1915 * and if we go to ringtones and select a ringtone, low-latency usecase
1916 * will be started on headset+speaker. As we can't enable headset+speaker
1917 * and headset devices at the same time, select_devices() switches the music
1918 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1919 * So when the ringtone playback is completed, how do we undo the same?
1920 *
1921 * We are relying on the out_set_parameters() call on deep-buffer output,
1922 * once the ringtone playback is ended.
1923 * NOTE: We should not check if the current devices are same as new devices.
1924 * Because select_devices() must be called to switch back the music
1925 * playback to headset.
1926 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001927 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001928 out->devices = val;
1929
1930 if (!out->standby)
1931 select_devices(adev, out->usecase);
1932
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001933 if (output_drives_call(adev, out)) {
1934 if(!voice_is_in_call(adev)) {
1935 if (adev->mode == AUDIO_MODE_IN_CALL) {
1936 adev->current_call_output = out;
1937 ret = voice_start_call(adev);
1938 }
1939 } else {
1940 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001941 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001942 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001943 }
1944 }
1945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001947 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001949
1950 if (out == adev->primary_output) {
1951 pthread_mutex_lock(&adev->lock);
1952 audio_extn_set_parameters(adev, parms);
1953 pthread_mutex_unlock(&adev->lock);
1954 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001955 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001956 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001957 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001958
1959 audio_extn_dts_create_state_notifier_node(out->usecase);
1960 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1961 popcount(out->channel_mask),
1962 out->playback_started);
1963
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001964 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001965 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301968error:
Eric Laurent994a6932013-07-17 11:51:42 -07001969 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 return ret;
1971}
1972
1973static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976 struct str_parms *query = str_parms_create_str(keys);
1977 char *str;
1978 char value[256];
1979 struct str_parms *reply = str_parms_create();
1980 size_t i, j;
1981 int ret;
1982 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001983
1984 if (!query || !reply) {
1985 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1986 return NULL;
1987 }
1988
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1991 if (ret >= 0) {
1992 value[0] = '\0';
1993 i = 0;
1994 while (out->supported_channel_masks[i] != 0) {
1995 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1996 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1997 if (!first) {
1998 strcat(value, "|");
1999 }
2000 strcat(value, out_channels_name_to_enum_table[j].name);
2001 first = false;
2002 break;
2003 }
2004 }
2005 i++;
2006 }
2007 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2008 str = str_parms_to_str(reply);
2009 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002010 voice_extn_out_get_parameters(out, query, reply);
2011 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002012 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002013 free(str);
2014 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002017
2018 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2019 if (ret >= 0) {
2020 value[0] = '\0';
2021 i = 0;
2022 first = true;
2023 while (out->supported_formats[i] != 0) {
2024 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2025 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2026 if (!first) {
2027 strcat(value, "|");
2028 }
2029 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2030 first = false;
2031 break;
2032 }
2033 }
2034 i++;
2035 }
2036 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2037 str = str_parms_to_str(reply);
2038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 str_parms_destroy(query);
2040 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return str;
2043}
2044
2045static uint32_t out_get_latency(const struct audio_stream_out *stream)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002048 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Alexy Josephaa54c872014-12-03 02:46:47 -08002050 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002051 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002052 } else {
2053 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002055 }
2056
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302057 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002058 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059}
2060
2061static int out_set_volume(struct audio_stream_out *stream, float left,
2062 float right)
2063{
Eric Laurenta9024de2013-04-04 09:19:12 -07002064 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 int volume[2];
2066
Eric Laurenta9024de2013-04-04 09:19:12 -07002067 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2068 /* only take left channel into account: the API is for stereo anyway */
2069 out->muted = (left == 0.0f);
2070 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002071 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002072 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2073 /*
2074 * Set mute or umute on HDMI passthrough stream.
2075 * Only take left channel into account.
2076 * Mute is 0 and unmute 1
2077 */
2078 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2079 } else {
2080 char mixer_ctl_name[128];
2081 struct audio_device *adev = out->dev;
2082 struct mixer_ctl *ctl;
2083 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002084 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002086 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2087 "Compress Playback %d Volume", pcm_device_id);
2088 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2089 if (!ctl) {
2090 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2091 __func__, mixer_ctl_name);
2092 return -EINVAL;
2093 }
2094 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2095 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2096 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2097 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002099 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 return -ENOSYS;
2102}
2103
2104static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2105 size_t bytes)
2106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302109 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002110 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302113
Naresh Tanniru80659832014-06-04 18:17:56 +05302114 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002115 // increase written size during SSR to avoid mismatch
2116 // with the written frames count in AF
2117 if (!is_offload_usecase(out->usecase))
2118 out->written += bytes / (out->config.channels * sizeof(short));
2119
Naresh Tanniru80659832014-06-04 18:17:56 +05302120 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302121 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302122 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302123 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002124 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302125 //during SSR for compress usecase we should return error to flinger
2126 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2127 pthread_mutex_unlock(&out->lock);
2128 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302129 }
2130 }
2131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002133 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002135 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2136 ret = voice_extn_compress_voip_start_output_stream(out);
2137 else
2138 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002139 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002142 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 goto exit;
2144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002147 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002148 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002149 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002150 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002151 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2152 out->send_new_metadata = 0;
2153 }
2154
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302156 if (ret < 0)
2157 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002158 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002159 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302160 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302162 } else if (-ENETRESET == ret) {
2163 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2164 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2165 pthread_mutex_unlock(&out->lock);
2166 out_standby(&out->stream.common);
2167 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302169 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002170 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002171 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 out->playback_started = 1;
2173 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002174
2175 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2176 popcount(out->channel_mask),
2177 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 }
2179 pthread_mutex_unlock(&out->lock);
2180 return ret;
2181 } else {
2182 if (out->pcm) {
2183 if (out->muted)
2184 memset((void *)buffer, 0, bytes);
2185 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002186 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2187 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2188 else
2189 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302190 if (ret < 0)
2191 ret = -errno;
2192 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002193 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 }
2196
2197exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302198 /* ToDo: There may be a corner case when SSR happens back to back during
2199 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302200 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302201 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302202 }
2203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 pthread_mutex_unlock(&out->lock);
2205
2206 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002207 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002208 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302209 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302210 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302211 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302212 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302213 out->standby = true;
2214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002216 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302217 out_get_sample_rate(&out->stream.common));
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 }
2220 return bytes;
2221}
2222
2223static int out_get_render_position(const struct audio_stream_out *stream,
2224 uint32_t *dsp_frames)
2225{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302227 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002228
2229 if (dsp_frames == NULL)
2230 return -EINVAL;
2231
2232 *dsp_frames = 0;
2233 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002234 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 pthread_mutex_lock(&out->lock);
2236 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302237 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302239 if (ret < 0)
2240 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 ALOGVV("%s rendered frames %d sample_rate %d",
2242 __func__, *dsp_frames, out->sample_rate);
2243 }
2244 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302245 if (-ENETRESET == ret) {
2246 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2247 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2248 return -EINVAL;
2249 } else if(ret < 0) {
2250 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2251 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302252 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2253 /*
2254 * Handle corner case where compress session is closed during SSR
2255 * and timestamp is queried
2256 */
2257 ALOGE(" ERROR: sound card not active, return error");
2258 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302259 } else {
2260 return 0;
2261 }
Zhou Song32a556e2015-05-05 10:46:56 +08002262 } else if (audio_is_linear_pcm(out->format)) {
2263 *dsp_frames = out->written;
2264 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 } else
2266 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267}
2268
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002269static int out_add_audio_effect(const struct audio_stream *stream __unused,
2270 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271{
2272 return 0;
2273}
2274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002275static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2276 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277{
2278 return 0;
2279}
2280
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002281static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2282 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283{
2284 return -EINVAL;
2285}
2286
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002287static int out_get_presentation_position(const struct audio_stream_out *stream,
2288 uint64_t *frames, struct timespec *timestamp)
2289{
2290 struct stream_out *out = (struct stream_out *)stream;
2291 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002292 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002293
2294 pthread_mutex_lock(&out->lock);
2295
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002296 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002297 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302298 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002299 &out->sample_rate);
2300 ALOGVV("%s rendered frames %ld sample_rate %d",
2301 __func__, dsp_frames, out->sample_rate);
2302 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302303 if (ret < 0)
2304 ret = -errno;
2305 if (-ENETRESET == ret) {
2306 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2307 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2308 ret = -EINVAL;
2309 } else
2310 ret = 0;
2311
Eric Laurent949a0892013-09-20 09:20:13 -07002312 /* this is the best we can do */
2313 clock_gettime(CLOCK_MONOTONIC, timestamp);
2314 }
2315 } else {
2316 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002317 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002318 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2319 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002320 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002321 // This adjustment accounts for buffering after app processor.
2322 // It is based on estimated DSP latency per use case, rather than exact.
2323 signed_frames -=
2324 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2325
Eric Laurent949a0892013-09-20 09:20:13 -07002326 // It would be unusual for this value to be negative, but check just in case ...
2327 if (signed_frames >= 0) {
2328 *frames = signed_frames;
2329 ret = 0;
2330 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002331 }
2332 }
2333 }
2334
2335 pthread_mutex_unlock(&out->lock);
2336
2337 return ret;
2338}
2339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340static int out_set_callback(struct audio_stream_out *stream,
2341 stream_callback_t callback, void *cookie)
2342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344
2345 ALOGV("%s", __func__);
2346 pthread_mutex_lock(&out->lock);
2347 out->offload_callback = callback;
2348 out->offload_cookie = cookie;
2349 pthread_mutex_unlock(&out->lock);
2350 return 0;
2351}
2352
2353static int out_pause(struct audio_stream_out* stream)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356 int status = -ENOSYS;
2357 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002358 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002359 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 pthread_mutex_lock(&out->lock);
2361 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302362 struct audio_device *adev = out->dev;
2363 int snd_scard_state = get_snd_card_state(adev);
2364
2365 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2366 status = compress_pause(out->compr);
2367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002369
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302370 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002371 audio_extn_dts_notify_playback_state(out->usecase, 0,
2372 out->sample_rate, popcount(out->channel_mask),
2373 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 }
2375 pthread_mutex_unlock(&out->lock);
2376 }
2377 return status;
2378}
2379
2380static int out_resume(struct audio_stream_out* stream)
2381{
2382 struct stream_out *out = (struct stream_out *)stream;
2383 int status = -ENOSYS;
2384 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002385 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002386 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 status = 0;
2388 pthread_mutex_lock(&out->lock);
2389 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302390 struct audio_device *adev = out->dev;
2391 int snd_scard_state = get_snd_card_state(adev);
2392
2393 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2394 status = compress_resume(out->compr);
2395
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002397
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302398 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2400 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 }
2402 pthread_mutex_unlock(&out->lock);
2403 }
2404 return status;
2405}
2406
2407static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 int status = -ENOSYS;
2411 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002412 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 pthread_mutex_lock(&out->lock);
2414 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2415 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2416 else
2417 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2418 pthread_mutex_unlock(&out->lock);
2419 }
2420 return status;
2421}
2422
2423static int out_flush(struct audio_stream_out* stream)
2424{
2425 struct stream_out *out = (struct stream_out *)stream;
2426 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002427 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002428 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429 pthread_mutex_lock(&out->lock);
2430 stop_compressed_output_l(out);
2431 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002432 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 return 0;
2434 }
2435 return -ENOSYS;
2436}
2437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438/** audio_stream_in implementation **/
2439static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2440{
2441 struct stream_in *in = (struct stream_in *)stream;
2442
2443 return in->config.rate;
2444}
2445
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002446static int in_set_sample_rate(struct audio_stream *stream __unused,
2447 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448{
2449 return -ENOSYS;
2450}
2451
2452static size_t in_get_buffer_size(const struct audio_stream *stream)
2453{
2454 struct stream_in *in = (struct stream_in *)stream;
2455
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002456 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2457 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002458 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2459 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002460
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002461 return in->config.period_size *
2462 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463}
2464
2465static uint32_t in_get_channels(const struct audio_stream *stream)
2466{
2467 struct stream_in *in = (struct stream_in *)stream;
2468
2469 return in->channel_mask;
2470}
2471
2472static audio_format_t in_get_format(const struct audio_stream *stream)
2473{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002474 struct stream_in *in = (struct stream_in *)stream;
2475
2476 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002479static int in_set_format(struct audio_stream *stream __unused,
2480 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481{
2482 return -ENOSYS;
2483}
2484
2485static int in_standby(struct audio_stream *stream)
2486{
2487 struct stream_in *in = (struct stream_in *)stream;
2488 struct audio_device *adev = in->dev;
2489 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302490 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2491 stream, in->usecase, use_case_table[in->usecase]);
2492
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002493 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2494 /* Ignore standby in case of voip call because the voip input
2495 * stream is closed in adev_close_input_stream()
2496 */
2497 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2498 return status;
2499 }
2500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002502 if (!in->standby && in->is_st_session) {
2503 ALOGD("%s: sound trigger pcm stop lab", __func__);
2504 audio_extn_sound_trigger_stop_lab(in);
2505 in->standby = 1;
2506 }
2507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002509 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002511 if (in->pcm) {
2512 pcm_close(in->pcm);
2513 in->pcm = NULL;
2514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 }
2518 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002519 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 return status;
2521}
2522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002523static int in_dump(const struct audio_stream *stream __unused,
2524 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525{
2526 return 0;
2527}
2528
2529static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2530{
2531 struct stream_in *in = (struct stream_in *)stream;
2532 struct audio_device *adev = in->dev;
2533 struct str_parms *parms;
2534 char *str;
2535 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002536 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302538 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 parms = str_parms_create_str(kvpairs);
2540
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302541 if (!parms)
2542 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002544 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002545
2546 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2547 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 val = atoi(value);
2549 /* no audio source uses val == 0 */
2550 if ((in->source != val) && (val != 0)) {
2551 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002552 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2553 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2554 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2555 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002556 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002557 err = voice_extn_compress_voip_open_input_stream(in);
2558 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002559 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002560 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002561 }
2562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 }
2564 }
2565
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002566 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2567 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002569 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 in->device = val;
2571 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002572 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002573 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 }
2575 }
2576
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002577done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002579 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580
2581 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302582error:
Eric Laurent994a6932013-07-17 11:51:42 -07002583 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 return ret;
2585}
2586
2587static char* in_get_parameters(const struct audio_stream *stream,
2588 const char *keys)
2589{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002590 struct stream_in *in = (struct stream_in *)stream;
2591 struct str_parms *query = str_parms_create_str(keys);
2592 char *str;
2593 char value[256];
2594 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002595
2596 if (!query || !reply) {
2597 ALOGE("in_get_parameters: failed to create query or reply");
2598 return NULL;
2599 }
2600
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002601 ALOGV("%s: enter: keys - %s", __func__, keys);
2602
2603 voice_extn_in_get_parameters(in, query, reply);
2604
2605 str = str_parms_to_str(reply);
2606 str_parms_destroy(query);
2607 str_parms_destroy(reply);
2608
2609 ALOGV("%s: exit: returns - %s", __func__, str);
2610 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611}
2612
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002613static int in_set_gain(struct audio_stream_in *stream __unused,
2614 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615{
2616 return 0;
2617}
2618
2619static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2620 size_t bytes)
2621{
2622 struct stream_in *in = (struct stream_in *)stream;
2623 struct audio_device *adev = in->dev;
2624 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302625 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302628
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002629 if (in->is_st_session) {
2630 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2631 /* Read from sound trigger HAL */
2632 audio_extn_sound_trigger_read(in, buffer, bytes);
2633 pthread_mutex_unlock(&in->lock);
2634 return bytes;
2635 }
2636
2637 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2638 ALOGD(" %s: sound card is not active/SSR state", __func__);
2639 ret= -EIO;;
2640 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302641 }
2642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002644 pthread_mutex_lock(&adev->lock);
2645 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2646 ret = voice_extn_compress_voip_start_input_stream(in);
2647 else
2648 ret = start_input_stream(in);
2649 pthread_mutex_unlock(&adev->lock);
2650 if (ret != 0) {
2651 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 }
2653 in->standby = 0;
2654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655
2656 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002657 if (audio_extn_ssr_get_enabled() &&
2658 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002659 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002660 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2661 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002662 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2663 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002664 else
2665 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302666 if (ret < 0)
2667 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 }
2669
2670 /*
2671 * Instead of writing zeroes here, we could trust the hardware
2672 * to always provide zeroes when muted.
2673 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302674 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2675 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 memset(buffer, 0, bytes);
2677
2678exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302679 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302680 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002681 if (-ENETRESET == ret)
2682 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 pthread_mutex_unlock(&in->lock);
2685
2686 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302687 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302688 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302689 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302690 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302691 in->standby = true;
2692 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302693 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002695 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002696 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302697 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 }
2699 return bytes;
2700}
2701
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002702static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703{
2704 return 0;
2705}
2706
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002707static int add_remove_audio_effect(const struct audio_stream *stream,
2708 effect_handle_t effect,
2709 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002711 struct stream_in *in = (struct stream_in *)stream;
2712 int status = 0;
2713 effect_descriptor_t desc;
2714
2715 status = (*effect)->get_descriptor(effect, &desc);
2716 if (status != 0)
2717 return status;
2718
2719 pthread_mutex_lock(&in->lock);
2720 pthread_mutex_lock(&in->dev->lock);
2721 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2722 in->enable_aec != enable &&
2723 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2724 in->enable_aec = enable;
2725 if (!in->standby)
2726 select_devices(in->dev, in->usecase);
2727 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002728 if (in->enable_ns != enable &&
2729 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2730 in->enable_ns = enable;
2731 if (!in->standby)
2732 select_devices(in->dev, in->usecase);
2733 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002734 pthread_mutex_unlock(&in->dev->lock);
2735 pthread_mutex_unlock(&in->lock);
2736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 return 0;
2738}
2739
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002740static int in_add_audio_effect(const struct audio_stream *stream,
2741 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742{
Eric Laurent994a6932013-07-17 11:51:42 -07002743 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002744 return add_remove_audio_effect(stream, effect, true);
2745}
2746
2747static int in_remove_audio_effect(const struct audio_stream *stream,
2748 effect_handle_t effect)
2749{
Eric Laurent994a6932013-07-17 11:51:42 -07002750 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002751 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752}
2753
2754static int adev_open_output_stream(struct audio_hw_device *dev,
2755 audio_io_handle_t handle,
2756 audio_devices_t devices,
2757 audio_output_flags_t flags,
2758 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002759 struct audio_stream_out **stream_out,
2760 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
2762 struct audio_device *adev = (struct audio_device *)dev;
2763 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002764 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002765 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302768
2769 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2770 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2771 ALOGE(" sound card is not active rejecting compress output open request");
2772 return -EINVAL;
2773 }
2774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2776
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302777 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2778 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2779 devices, flags, &out->stream);
2780
2781
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002782 if (!out) {
2783 return -ENOMEM;
2784 }
2785
Haynes Mathew George204045b2015-02-25 20:32:03 -08002786 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2787 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 if (devices == AUDIO_DEVICE_NONE)
2790 devices = AUDIO_DEVICE_OUT_SPEAKER;
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 out->flags = flags;
2793 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002794 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002795 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002796 out->sample_rate = config->sample_rate;
2797 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2798 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002799 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002800 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002801 out->non_blocking = 0;
2802 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803
2804 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002805 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2806 (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);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002898 if (audio_is_offload_pcm(config->offload_info.format)) {
2899 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};