blob: 6951fe4462b6a27573cde146e8855f57941c470f [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
vivek mehta0ea887a2015-08-26 14:01:20 -0700180 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
181
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700183 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700184 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700185 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700186 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800187 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800188 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700190
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700191 [USECASE_VOICE2_CALL] = "voice2-call",
192 [USECASE_VOLTE_CALL] = "volte-call",
193 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800194 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800195 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
196 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800197 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700198 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
199 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
200 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800201 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
202 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
203 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
204
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700205 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
206 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700207 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
208 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700209
210 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
211 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700212};
213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700214static const audio_usecase_t offload_usecases[] = {
215 USECASE_AUDIO_PLAYBACK_OFFLOAD,
216#ifdef MULTIPLE_OFFLOAD_ENABLED
217 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
225#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700226 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700227};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228
229#define STRING_TO_ENUM(string) { #string, string }
230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800231struct string_to_enum {
232 const char *name;
233 uint32_t value;
234};
235
236static const struct string_to_enum out_channels_name_to_enum_table[] = {
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
244};
245
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700246static const struct string_to_enum out_formats_name_to_enum_table[] = {
247 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
250};
251
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700252static struct audio_device *adev = NULL;
253static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700254static unsigned int audio_device_ref_count;
255
Haynes Mathew George5191a852013-09-11 14:19:36 -0700256static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800257
vivek mehtaa76401a2015-04-24 14:12:15 -0700258__attribute__ ((visibility ("default")))
259bool audio_hw_send_gain_dep_calibration(int level) {
260 bool ret_val = false;
261 ALOGV("%s: called ... ", __func__);
262
263 pthread_mutex_lock(&adev_init_lock);
264
265 if (adev != NULL && adev->platform != NULL) {
266 pthread_mutex_lock(&adev->lock);
267 ret_val = platform_send_gain_dep_cal(adev->platform, level);
268 pthread_mutex_unlock(&adev->lock);
269 } else {
270 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
271 }
272
273 pthread_mutex_unlock(&adev_init_lock);
274
275 return ret_val;
276}
277
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800278static int check_and_set_gapless_mode(struct audio_device *adev) {
279
280
281 char value[PROPERTY_VALUE_MAX] = {0};
282 bool gapless_enabled = false;
283 const char *mixer_ctl_name = "Compress Gapless Playback";
284 struct mixer_ctl *ctl;
285
286 ALOGV("%s:", __func__);
287 property_get("audio.offload.gapless.enabled", value, NULL);
288 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
289
290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
291 if (!ctl) {
292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
293 __func__, mixer_ctl_name);
294 return -EINVAL;
295 }
296
297 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
298 ALOGE("%s: Could not set gapless mode %d",
299 __func__, gapless_enabled);
300 return -EINVAL;
301 }
302 return 0;
303}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305static bool is_supported_format(audio_format_t format)
306{
Eric Laurent86e17132013-09-12 17:49:30 -0700307 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530308 format == AUDIO_FORMAT_AAC_LC ||
309 format == AUDIO_FORMAT_AAC_HE_V1 ||
310 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800311 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700312 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700313 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800314 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530315 format == AUDIO_FORMAT_ALAC ||
316 format == AUDIO_FORMAT_APE ||
317 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800318 format == AUDIO_FORMAT_WMA ||
319 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800320 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700321
322 return false;
323}
324
325static int get_snd_codec_id(audio_format_t format)
326{
327 int id = 0;
328
Ashish Jainf9b78162014-08-25 20:36:25 +0530329 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700330 case AUDIO_FORMAT_MP3:
331 id = SND_AUDIOCODEC_MP3;
332 break;
333 case AUDIO_FORMAT_AAC:
334 id = SND_AUDIOCODEC_AAC;
335 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530336 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700337 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800338 id = SND_AUDIOCODEC_PCM;
339 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700340 case AUDIO_FORMAT_FLAC:
341 id = SND_AUDIOCODEC_FLAC;
342 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530343 case AUDIO_FORMAT_ALAC:
344 id = SND_AUDIOCODEC_ALAC;
345 break;
346 case AUDIO_FORMAT_APE:
347 id = SND_AUDIOCODEC_APE;
348 break;
349 case AUDIO_FORMAT_VORBIS:
350 id = SND_AUDIOCODEC_VORBIS;
351 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800352 case AUDIO_FORMAT_WMA:
353 id = SND_AUDIOCODEC_WMA;
354 break;
355 case AUDIO_FORMAT_WMA_PRO:
356 id = SND_AUDIOCODEC_WMA_PRO;
357 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700358 default:
Mingming Yin90310102013-11-13 16:57:00 -0800359 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 }
361
362 return id;
363}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800364
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530365int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530366{
367 int snd_scard_state;
368
369 if (!adev)
370 return SND_CARD_STATE_OFFLINE;
371
372 pthread_mutex_lock(&adev->snd_card_status.lock);
373 snd_scard_state = adev->snd_card_status.state;
374 pthread_mutex_unlock(&adev->snd_card_status.lock);
375
376 return snd_scard_state;
377}
378
379static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
380{
381 if (!adev)
382 return -ENOSYS;
383
384 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700385 if (adev->snd_card_status.state != snd_scard_state) {
386 adev->snd_card_status.state = snd_scard_state;
387 platform_snd_card_update(adev->platform, snd_scard_state);
388 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530389 pthread_mutex_unlock(&adev->snd_card_status.lock);
390
391 return 0;
392}
393
Avinash Vaish71a8b972014-07-24 15:36:33 +0530394static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
395 struct audio_usecase *uc_info)
396{
397 struct listnode *node;
398 struct audio_usecase *usecase;
399
400 if (uc_info == NULL)
401 return -EINVAL;
402
403 /* Re-route all voice usecases on the shared backend other than the
404 specified usecase to new snd devices */
405 list_for_each(node, &adev->usecase_list) {
406 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800407 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530408 enable_audio_route(adev, usecase);
409 }
410 return 0;
411}
412
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700413int pcm_ioctl(struct pcm *pcm, int request, ...)
414{
415 va_list ap;
416 void * arg;
417 int pcm_fd = *(int*)pcm;
418
419 va_start(ap, request);
420 arg = va_arg(ap, void *);
421 va_end(ap);
422
423 return ioctl(pcm_fd, request, arg);
424}
425
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700426int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700427 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700429 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700430 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800431
432 if (usecase == NULL)
433 return -EINVAL;
434
435 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
436
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800442#ifdef DS1_DOLBY_DAP_ENABLED
443 audio_extn_dolby_set_dmid(adev);
444 audio_extn_dolby_set_endpoint(adev);
445#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700446 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700447 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530448 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700449 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700450 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800451 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700452 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700453 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
454 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 ALOGV("%s: exit", __func__);
456 return 0;
457}
458
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700459int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700460 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700462 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700463 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800464
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530465 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466 return -EINVAL;
467
468 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 if (usecase->type == PCM_CAPTURE)
470 snd_device = usecase->in_snd_device;
471 else
472 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800473 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700474 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700475 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
476 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700477 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530478 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479 ALOGV("%s: exit", __func__);
480 return 0;
481}
482
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700483int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700484 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700486 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
487
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800488 if (snd_device < SND_DEVICE_MIN ||
489 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800490 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800491 return -EINVAL;
492 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700493
494 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700495
496 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
497 ALOGE("%s: Invalid sound device returned", __func__);
498 return -EINVAL;
499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700500 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700501 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700502 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700503 return 0;
504 }
505
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700506 if (audio_extn_spkr_prot_is_enabled())
507 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700508 /* start usb playback thread */
509 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
510 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
511 audio_extn_usb_start_playback(adev);
512
513 /* start usb capture thread */
514 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
515 audio_extn_usb_start_capture(adev);
516
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800517 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
518 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700519 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700520 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
521 adev->snd_dev_ref_cnt[snd_device]--;
522 return -EINVAL;
523 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200524 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800525 if (audio_extn_spkr_prot_start_processing(snd_device)) {
526 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200527 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800528 return -EINVAL;
529 }
530 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700531 ALOGV("%s: snd_device(%d: %s)", __func__,
532 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700533 /* due to the possibility of calibration overwrite between listen
534 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700535 audio_extn_sound_trigger_update_device_status(snd_device,
536 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530537 audio_extn_listen_update_device_status(snd_device,
538 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700539 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700541 audio_extn_sound_trigger_update_device_status(snd_device,
542 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530543 audio_extn_listen_update_device_status(snd_device,
544 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700545 return -EINVAL;
546 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300547 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700548 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550 return 0;
551}
552
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700553int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700554 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700556 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
557
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800558 if (snd_device < SND_DEVICE_MIN ||
559 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800560 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800561 return -EINVAL;
562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
564 ALOGE("%s: device ref cnt is already 0", __func__);
565 return -EINVAL;
566 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700568 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700569
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700570 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
571 ALOGE("%s: Invalid sound device returned", __func__);
572 return -EINVAL;
573 }
574
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700576 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700577 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800578 /* exit usb play back thread */
579 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
580 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
581 audio_extn_usb_stop_playback();
582
583 /* exit usb capture thread */
584 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700585 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800586
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800587 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
588 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700589 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700590 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300591 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700592 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300593 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700594
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200595 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700596 audio_extn_sound_trigger_update_device_status(snd_device,
597 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530598 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800599 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 return 0;
603}
604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605static void check_usecases_codec_backend(struct audio_device *adev,
606 struct audio_usecase *uc_info,
607 snd_device_t snd_device)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611 bool switch_device[AUDIO_USECASE_MAX];
612 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800613 int backend_idx = DEFAULT_CODEC_BACKEND;
614 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615
616 /*
617 * This function is to make sure that all the usecases that are active on
618 * the hardware codec backend are always routed to any one device that is
619 * handled by the hardware codec.
620 * For example, if low-latency and deep-buffer usecases are currently active
621 * on speaker and out_set_parameters(headset) is received on low-latency
622 * output, then we have to make sure deep-buffer is also switched to headset,
623 * because of the limitation that both the devices cannot be enabled
624 * at the same time as they share the same backend.
625 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700626 /*
627 * This call is to check if we need to force routing for a particular stream
628 * If there is a backend configuration change for the device when a
629 * new stream starts, then ADM needs to be closed and re-opened with the new
630 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800631 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700632 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
634 snd_device);
635 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800637 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800638 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639 for (i = 0; i < AUDIO_USECASE_MAX; i++)
640 switch_device[i] = false;
641
642 list_for_each(node, &adev->usecase_list) {
643 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800644
645 if (usecase == uc_info)
646 continue;
647 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
648 ALOGV("%s: backend_idx: %d,"
649 "usecase_backend_idx: %d, curr device: %s, usecase device:"
650 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530651 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800652
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800653 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700654 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800655 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
656 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530657 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700659 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700660 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661 switch_device[usecase->id] = true;
662 num_uc_to_switch++;
663 }
664 }
665
666 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700667 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530669 /* Make sure the previous devices to be disabled first and then enable the
670 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 list_for_each(node, &adev->usecase_list) {
672 usecase = node_to_item(node, struct audio_usecase, list);
673 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700674 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 }
676 }
677
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700678 list_for_each(node, &adev->usecase_list) {
679 usecase = node_to_item(node, struct audio_usecase, list);
680 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700681 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700682 }
683 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 /* Re-route all the usecases on the shared backend other than the
686 specified usecase to new snd devices */
687 list_for_each(node, &adev->usecase_list) {
688 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530689 /* Update the out_snd_device only for the usecases that are enabled here */
690 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
691 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530692 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 }
694 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695 }
696}
697
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700698static void check_and_route_capture_usecases(struct audio_device *adev,
699 struct audio_usecase *uc_info,
700 snd_device_t snd_device)
701{
702 struct listnode *node;
703 struct audio_usecase *usecase;
704 bool switch_device[AUDIO_USECASE_MAX];
705 int i, num_uc_to_switch = 0;
706
707 /*
708 * This function is to make sure that all the active capture usecases
709 * are always routed to the same input sound device.
710 * For example, if audio-record and voice-call usecases are currently
711 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
712 * is received for voice call then we have to make sure that audio-record
713 * usecase is also switched to earpiece i.e. voice-dmic-ef,
714 * because of the limitation that two devices cannot be enabled
715 * at the same time if they share the same backend.
716 */
717 for (i = 0; i < AUDIO_USECASE_MAX; i++)
718 switch_device[i] = false;
719
720 list_for_each(node, &adev->usecase_list) {
721 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800722 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700723 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700724 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700725 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
726 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700727 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
729 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700730 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700731 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 switch_device[usecase->id] = true;
733 num_uc_to_switch++;
734 }
735 }
736
737 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700738 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530740 /* Make sure the previous devices to be disabled first and then enable the
741 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 list_for_each(node, &adev->usecase_list) {
743 usecase = node_to_item(node, struct audio_usecase, list);
744 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700745 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800746 }
747 }
748
749 list_for_each(node, &adev->usecase_list) {
750 usecase = node_to_item(node, struct audio_usecase, list);
751 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700752 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700753 }
754 }
755
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 /* Re-route all the usecases on the shared backend other than the
757 specified usecase to new snd devices */
758 list_for_each(node, &adev->usecase_list) {
759 usecase = node_to_item(node, struct audio_usecase, list);
760 /* Update the in_snd_device only before enabling the audio route */
761 if (switch_device[usecase->id] ) {
762 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800763 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530764 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700765 }
766 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 }
768}
769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700771static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700773 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700774 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775
776 switch (channels) {
777 /*
778 * Do not handle stereo output in Multi-channel cases
779 * Stereo case is handled in normal playback path
780 */
781 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700782 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788 break;
789 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700790 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 break;
798 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700799 ALOGE("HDMI does not support multi channel playback");
800 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801 break;
802 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804}
805
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800806audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
807 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700808{
809 struct audio_usecase *usecase;
810 struct listnode *node;
811
812 list_for_each(node, &adev->usecase_list) {
813 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800814 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815 ALOGV("%s: usecase id %d", __func__, usecase->id);
816 return usecase->id;
817 }
818 }
819 return USECASE_INVALID;
820}
821
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700822struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700823 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700824{
825 struct audio_usecase *usecase;
826 struct listnode *node;
827
828 list_for_each(node, &adev->usecase_list) {
829 usecase = node_to_item(node, struct audio_usecase, list);
830 if (usecase->id == uc_id)
831 return usecase;
832 }
833 return NULL;
834}
835
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700836int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800838 snd_device_t out_snd_device = SND_DEVICE_NONE;
839 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 struct audio_usecase *usecase = NULL;
841 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800842 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800843 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800844 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800845 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848 usecase = get_usecase_from_list(adev, uc_id);
849 if (usecase == NULL) {
850 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
851 return -EINVAL;
852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800855 (usecase->type == VOIP_CALL) ||
856 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700857 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800858 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700859 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 usecase->devices = usecase->stream.out->devices;
861 } else {
862 /*
863 * If the voice call is active, use the sound devices of voice call usecase
864 * so that it would not result any device switch. All the usecases will
865 * be switched to new device when select_devices() is called for voice call
866 * usecase. This is to avoid switching devices for voice call when
867 * check_usecases_codec_backend() is called below.
868 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700869 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700870 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800871 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700872 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
873 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 in_snd_device = vc_usecase->in_snd_device;
875 out_snd_device = vc_usecase->out_snd_device;
876 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 } else if (voice_extn_compress_voip_is_active(adev)) {
878 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700879 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530880 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700881 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800882 in_snd_device = voip_usecase->in_snd_device;
883 out_snd_device = voip_usecase->out_snd_device;
884 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800885 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800886 hfp_ucid = audio_extn_hfp_get_usecase();
887 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700888 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800889 in_snd_device = hfp_usecase->in_snd_device;
890 out_snd_device = hfp_usecase->out_snd_device;
891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 }
893 if (usecase->type == PCM_PLAYBACK) {
894 usecase->devices = usecase->stream.out->devices;
895 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700896 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700897 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800898 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700899 if (usecase->stream.out == adev->primary_output &&
900 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800901 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700902 select_devices(adev, adev->active_input->usecase);
903 }
904 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 } else if (usecase->type == PCM_CAPTURE) {
906 usecase->devices = usecase->stream.in->device;
907 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700908 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700909 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530910 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
911 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
912 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
913 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700914 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800915 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700916 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
917 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700918 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700919 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700920 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 }
922 }
923
924 if (out_snd_device == usecase->out_snd_device &&
925 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800926 return 0;
927 }
928
sangwoobc677242013-08-08 16:53:43 +0900929 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700930 out_snd_device, platform_get_snd_device_name(out_snd_device),
931 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 /*
934 * Limitation: While in call, to do a device switch we need to disable
935 * and enable both RX and TX devices though one of them is same as current
936 * device.
937 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700938 if ((usecase->type == VOICE_CALL) &&
939 (usecase->in_snd_device != SND_DEVICE_NONE) &&
940 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700941 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700942 }
943
944 if (((usecase->type == VOICE_CALL) ||
945 (usecase->type == VOIP_CALL)) &&
946 (usecase->out_snd_device != SND_DEVICE_NONE)) {
947 /* Disable sidetone only if voice/voip call already exists */
948 if (voice_is_call_state_active(adev) ||
949 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700950 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800951 }
952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 /* Disable current sound devices */
954 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700955 disable_audio_route(adev, usecase);
956 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957 }
958
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700960 disable_audio_route(adev, usecase);
961 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962 }
963
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800964 /* Applicable only on the targets that has external modem.
965 * New device information should be sent to modem before enabling
966 * the devices to reduce in-call device switch time.
967 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700968 if ((usecase->type == VOICE_CALL) &&
969 (usecase->in_snd_device != SND_DEVICE_NONE) &&
970 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800971 status = platform_switch_voice_call_enable_device_config(adev->platform,
972 out_snd_device,
973 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700974 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800975
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 /* Enable new sound devices */
977 if (out_snd_device != SND_DEVICE_NONE) {
978 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
979 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981 }
982
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700983 if (in_snd_device != SND_DEVICE_NONE) {
984 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700985 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987
Avinash Vaish71a8b972014-07-24 15:36:33 +0530988 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700989 status = platform_switch_voice_call_device_post(adev->platform,
990 out_snd_device,
991 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700993 /* Enable sidetone only if voice/voip call already exists */
994 if (voice_is_call_state_active(adev) ||
995 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700996 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530997 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800998
sangwoo170731f2013-06-08 15:36:36 +0900999 usecase->in_snd_device = in_snd_device;
1000 usecase->out_snd_device = out_snd_device;
1001
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301002 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001003 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301004 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001005 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301006 usecase->stream.out->flags,
1007 usecase->stream.out->format,
1008 usecase->stream.out->sample_rate,
1009 usecase->stream.out->bit_width,
1010 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001011 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301012 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001013
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001014 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001015
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001016 /* Applicable only on the targets that has external modem.
1017 * Enable device command should be sent to modem only after
1018 * enabling voice call mixer controls
1019 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001020 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001021 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1022 out_snd_device,
1023 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301024 ALOGD("%s: done",__func__);
1025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 return status;
1027}
1028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029static int stop_input_stream(struct stream_in *in)
1030{
1031 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 struct audio_usecase *uc_info;
1033 struct audio_device *adev = in->dev;
1034
Eric Laurentc8400632013-02-14 19:04:54 -08001035 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036
Eric Laurent994a6932013-07-17 11:51:42 -07001037 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 uc_info = get_usecase_from_list(adev, in->usecase);
1040 if (uc_info == NULL) {
1041 ALOGE("%s: Could not find the usecase (%d) in the list",
1042 __func__, in->usecase);
1043 return -EINVAL;
1044 }
1045
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001046 /* Close in-call recording streams */
1047 voice_check_and_stop_incall_rec_usecase(adev, in);
1048
Eric Laurent150dbfe2013-02-27 14:31:02 -08001049 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001050 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051
1052 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001053 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001055 list_remove(&uc_info->list);
1056 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Eric Laurent994a6932013-07-17 11:51:42 -07001058 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 return ret;
1060}
1061
1062int start_input_stream(struct stream_in *in)
1063{
1064 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001065 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 struct audio_usecase *uc_info;
1067 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301068 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069
Mingming Yine62d7842013-10-25 16:26:03 -07001070 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301071 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1072 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001073
Naresh Tanniru80659832014-06-04 18:17:56 +05301074
1075 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301076 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301077 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301078 goto error_config;
1079 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301080
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001081 /* Check if source matches incall recording usecase criteria */
1082 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1083 if (ret)
1084 goto error_config;
1085 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001086 ALOGD("%s: Updated usecase(%d: %s)",
1087 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001088
Eric Laurentb23d5282013-05-14 15:27:20 -07001089 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 if (in->pcm_device_id < 0) {
1091 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1092 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001093 ret = -EINVAL;
1094 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096
1097 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001099
1100 if (!uc_info) {
1101 ret = -ENOMEM;
1102 goto error_config;
1103 }
1104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 uc_info->id = in->usecase;
1106 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001107 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 uc_info->devices = in->device;
1109 uc_info->in_snd_device = SND_DEVICE_NONE;
1110 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001112 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301113 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115
Eric Laurentc8400632013-02-14 19:04:54 -08001116 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001117 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1118
1119 unsigned int flags = PCM_IN;
1120 unsigned int pcm_open_retry_count = 0;
1121
1122 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1123 flags |= PCM_MMAP | PCM_NOIRQ;
1124 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1125 }
1126
1127 while (1) {
1128 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1129 flags, &in->config);
1130 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1131 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1132 if (in->pcm != NULL) {
1133 pcm_close(in->pcm);
1134 in->pcm = NULL;
1135 }
1136 if (pcm_open_retry_count-- == 0) {
1137 ret = -EIO;
1138 goto error_open;
1139 }
1140 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1141 continue;
1142 }
1143 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001144 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301145 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301146
Eric Laurent994a6932013-07-17 11:51:42 -07001147 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001148 return ret;
1149
1150error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301152 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001153
1154error_config:
1155 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001157
1158 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159}
1160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001161/* must be called with out->lock locked */
1162static int send_offload_cmd_l(struct stream_out* out, int command)
1163{
1164 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1165
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001166 if (!cmd) {
1167 ALOGE("failed to allocate mem for command 0x%x", command);
1168 return -ENOMEM;
1169 }
1170
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001171 ALOGVV("%s %d", __func__, command);
1172
1173 cmd->cmd = command;
1174 list_add_tail(&out->offload_cmd_list, &cmd->node);
1175 pthread_cond_signal(&out->offload_cond);
1176 return 0;
1177}
1178
1179/* must be called iwth out->lock locked */
1180static void stop_compressed_output_l(struct stream_out *out)
1181{
1182 out->offload_state = OFFLOAD_STATE_IDLE;
1183 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001184 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001185 if (out->compr != NULL) {
1186 compress_stop(out->compr);
1187 while (out->offload_thread_blocked) {
1188 pthread_cond_wait(&out->cond, &out->lock);
1189 }
1190 }
1191}
1192
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001193bool is_offload_usecase(audio_usecase_t uc_id)
1194{
1195 unsigned int i;
1196 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1197 if (uc_id == offload_usecases[i])
1198 return true;
1199 }
1200 return false;
1201}
1202
1203static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1204{
1205 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1206 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1207 char value[PROPERTY_VALUE_MAX] = {0};
1208
1209 property_get("audio.offload.multiple.enabled", value, NULL);
1210 if (!(atoi(value) || !strncmp("true", value, 4)))
1211 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1212
1213 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1214 for (i = 0; i < num_usecase; i++) {
1215 if (!(adev->offload_usecases_state & (0x1<<i))) {
1216 adev->offload_usecases_state |= 0x1 << i;
1217 ret = offload_usecases[i];
1218 break;
1219 }
1220 }
1221 ALOGV("%s: offload usecase is %d", __func__, ret);
1222 return ret;
1223}
1224
1225static void free_offload_usecase(struct audio_device *adev,
1226 audio_usecase_t uc_id)
1227{
1228 unsigned int i;
1229 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1230 if (offload_usecases[i] == uc_id) {
1231 adev->offload_usecases_state &= ~(0x1<<i);
1232 break;
1233 }
1234 }
1235 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1236}
1237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238static void *offload_thread_loop(void *context)
1239{
1240 struct stream_out *out = (struct stream_out *) context;
1241 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001242 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001243
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001244 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1245 set_sched_policy(0, SP_FOREGROUND);
1246 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1247
1248 ALOGV("%s", __func__);
1249 pthread_mutex_lock(&out->lock);
1250 for (;;) {
1251 struct offload_cmd *cmd = NULL;
1252 stream_callback_event_t event;
1253 bool send_callback = false;
1254
1255 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1256 __func__, list_empty(&out->offload_cmd_list),
1257 out->offload_state);
1258 if (list_empty(&out->offload_cmd_list)) {
1259 ALOGV("%s SLEEPING", __func__);
1260 pthread_cond_wait(&out->offload_cond, &out->lock);
1261 ALOGV("%s RUNNING", __func__);
1262 continue;
1263 }
1264
1265 item = list_head(&out->offload_cmd_list);
1266 cmd = node_to_item(item, struct offload_cmd, node);
1267 list_remove(item);
1268
1269 ALOGVV("%s STATE %d CMD %d out->compr %p",
1270 __func__, out->offload_state, cmd->cmd, out->compr);
1271
1272 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1273 free(cmd);
1274 break;
1275 }
1276
1277 if (out->compr == NULL) {
1278 ALOGE("%s: Compress handle is NULL", __func__);
1279 pthread_cond_signal(&out->cond);
1280 continue;
1281 }
1282 out->offload_thread_blocked = true;
1283 pthread_mutex_unlock(&out->lock);
1284 send_callback = false;
1285 switch(cmd->cmd) {
1286 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001287 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001288 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001289 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 send_callback = true;
1291 event = STREAM_CBK_EVENT_WRITE_READY;
1292 break;
1293 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001294 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301295 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001296 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301297 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001298 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301299 if (ret < 0)
1300 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301301 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301302 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001303 compress_drain(out->compr);
1304 else
1305 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301306 if (ret != -ENETRESET) {
1307 send_callback = true;
1308 event = STREAM_CBK_EVENT_DRAIN_READY;
1309 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1310 } else
1311 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 break;
1313 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001314 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001316 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 send_callback = true;
1318 event = STREAM_CBK_EVENT_DRAIN_READY;
1319 break;
1320 default:
1321 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1322 break;
1323 }
1324 pthread_mutex_lock(&out->lock);
1325 out->offload_thread_blocked = false;
1326 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001327 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001328 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001330 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001331 free(cmd);
1332 }
1333
1334 pthread_cond_signal(&out->cond);
1335 while (!list_empty(&out->offload_cmd_list)) {
1336 item = list_head(&out->offload_cmd_list);
1337 list_remove(item);
1338 free(node_to_item(item, struct offload_cmd, node));
1339 }
1340 pthread_mutex_unlock(&out->lock);
1341
1342 return NULL;
1343}
1344
1345static int create_offload_callback_thread(struct stream_out *out)
1346{
1347 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1348 list_init(&out->offload_cmd_list);
1349 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1350 offload_thread_loop, out);
1351 return 0;
1352}
1353
1354static int destroy_offload_callback_thread(struct stream_out *out)
1355{
1356 pthread_mutex_lock(&out->lock);
1357 stop_compressed_output_l(out);
1358 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1359
1360 pthread_mutex_unlock(&out->lock);
1361 pthread_join(out->offload_thread, (void **) NULL);
1362 pthread_cond_destroy(&out->offload_cond);
1363
1364 return 0;
1365}
1366
Eric Laurent07eeafd2013-10-06 12:52:49 -07001367static bool allow_hdmi_channel_config(struct audio_device *adev)
1368{
1369 struct listnode *node;
1370 struct audio_usecase *usecase;
1371 bool ret = true;
1372
1373 list_for_each(node, &adev->usecase_list) {
1374 usecase = node_to_item(node, struct audio_usecase, list);
1375 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1376 /*
1377 * If voice call is already existing, do not proceed further to avoid
1378 * disabling/enabling both RX and TX devices, CSD calls, etc.
1379 * Once the voice call done, the HDMI channels can be configured to
1380 * max channels of remaining use cases.
1381 */
1382 if (usecase->id == USECASE_VOICE_CALL) {
1383 ALOGD("%s: voice call is active, no change in HDMI channels",
1384 __func__);
1385 ret = false;
1386 break;
1387 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1388 ALOGD("%s: multi channel playback is active, "
1389 "no change in HDMI channels", __func__);
1390 ret = false;
1391 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001392 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001393 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001394 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1395 ", no change in HDMI channels", __func__,
1396 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001397 ret = false;
1398 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001399 }
1400 }
1401 }
1402 return ret;
1403}
1404
1405static int check_and_set_hdmi_channels(struct audio_device *adev,
1406 unsigned int channels)
1407{
1408 struct listnode *node;
1409 struct audio_usecase *usecase;
1410
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001411 unsigned int supported_channels = platform_edid_get_max_channels(
1412 adev->platform);
1413 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 /* Check if change in HDMI channel config is allowed */
1415 if (!allow_hdmi_channel_config(adev))
1416 return 0;
1417
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001418 if (channels > supported_channels)
1419 channels = supported_channels;
1420
Eric Laurent07eeafd2013-10-06 12:52:49 -07001421 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001422 ALOGD("%s: Requested channels are same as current channels(%d)",
1423 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001424 return 0;
1425 }
1426
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001427 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001429 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 adev->cur_hdmi_channels = channels;
1431
1432 /*
1433 * Deroute all the playback streams routed to HDMI so that
1434 * the back end is deactivated. Note that backend will not
1435 * be deactivated if any one stream is connected to it.
1436 */
1437 list_for_each(node, &adev->usecase_list) {
1438 usecase = node_to_item(node, struct audio_usecase, list);
1439 if (usecase->type == PCM_PLAYBACK &&
1440 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001441 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001442 }
1443 }
1444
1445 /*
1446 * Enable all the streams disabled above. Now the HDMI backend
1447 * will be activated with new channel configuration
1448 */
1449 list_for_each(node, &adev->usecase_list) {
1450 usecase = node_to_item(node, struct audio_usecase, list);
1451 if (usecase->type == PCM_PLAYBACK &&
1452 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001453 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001454 }
1455 }
1456
1457 return 0;
1458}
1459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460static int stop_output_stream(struct stream_out *out)
1461{
1462 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 struct audio_usecase *uc_info;
1464 struct audio_device *adev = out->dev;
1465
Eric Laurent994a6932013-07-17 11:51:42 -07001466 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 uc_info = get_usecase_from_list(adev, out->usecase);
1469 if (uc_info == NULL) {
1470 ALOGE("%s: Could not find the usecase (%d) in the list",
1471 __func__, out->usecase);
1472 return -EINVAL;
1473 }
1474
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001475 if (is_offload_usecase(out->usecase) &&
1476 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001477 if (adev->visualizer_stop_output != NULL)
1478 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001479
1480 audio_extn_dts_remove_state_notifier_node(out->usecase);
1481
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001482 if (adev->offload_effects_stop_output != NULL)
1483 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1484 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001485
Eric Laurent150dbfe2013-02-27 14:31:02 -08001486 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001487 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488
1489 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001490 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001492 list_remove(&uc_info->list);
1493 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001495 if (is_offload_usecase(out->usecase) &&
1496 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1497 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1498 ALOGV("Disable passthrough , reset mixer to pcm");
1499 /* NO_PASSTHROUGH */
1500 out->compr_config.codec->compr_passthr = 0;
1501 audio_extn_dolby_set_hdmi_config(adev, out);
1502 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1503 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001504 /* Must be called after removing the usecase from list */
1505 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1506 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1507
Eric Laurent994a6932013-07-17 11:51:42 -07001508 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 return ret;
1510}
1511
1512int start_output_stream(struct stream_out *out)
1513{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001515 int sink_channels = 0;
1516 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 struct audio_usecase *uc_info;
1518 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301519 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001521 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1522 ret = -EINVAL;
1523 goto error_config;
1524 }
1525
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301526 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1527 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1528 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301529
Naresh Tanniru80659832014-06-04 18:17:56 +05301530 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301531 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301532 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301533 goto error_config;
1534 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301535
Eric Laurentb23d5282013-05-14 15:27:20 -07001536 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 if (out->pcm_device_id < 0) {
1538 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1539 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001540 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001541 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542 }
1543
1544 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001545
1546 if (!uc_info) {
1547 ret = -ENOMEM;
1548 goto error_config;
1549 }
1550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551 uc_info->id = out->usecase;
1552 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001553 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 uc_info->devices = out->devices;
1555 uc_info->in_snd_device = SND_DEVICE_NONE;
1556 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001558 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001559 if (is_offload_usecase(out->usecase)) {
1560 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001561 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1562 }
1563 }
Mingming Yin9c041392014-05-01 15:37:31 -07001564 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1565 if (!strncmp("true", prop_value, 4)) {
1566 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001567 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1568 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001569 check_and_set_hdmi_channels(adev, sink_channels);
1570 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001571 if (is_offload_usecase(out->usecase)) {
1572 unsigned int ch_count = out->compr_config.codec->ch_in;
1573 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1574 /* backend channel config for passthrough stream is stereo */
1575 ch_count = 2;
1576 check_and_set_hdmi_channels(adev, ch_count);
1577 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001578 check_and_set_hdmi_channels(adev, out->config.channels);
1579 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001580 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001581 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001582 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 select_devices(adev, out->usecase);
1585
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001586 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1587 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001588 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001589 unsigned int flags = PCM_OUT;
1590 unsigned int pcm_open_retry_count = 0;
1591 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1592 flags |= PCM_MMAP | PCM_NOIRQ;
1593 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1594 } else
1595 flags |= PCM_MONOTONIC;
1596
1597 while (1) {
1598 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1599 flags, &out->config);
1600 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1601 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1602 if (out->pcm != NULL) {
1603 pcm_close(out->pcm);
1604 out->pcm = NULL;
1605 }
1606 if (pcm_open_retry_count-- == 0) {
1607 ret = -EIO;
1608 goto error_open;
1609 }
1610 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1611 continue;
1612 }
1613 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001614 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001615 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1616 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001618 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1619 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001621 out->compr = compress_open(adev->snd_card,
1622 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001623 COMPRESS_IN, &out->compr_config);
1624 if (out->compr && !is_compress_ready(out->compr)) {
1625 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1626 compress_close(out->compr);
1627 out->compr = NULL;
1628 ret = -EIO;
1629 goto error_open;
1630 }
1631 if (out->offload_callback)
1632 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001633
Fred Oh3f43e742015-03-04 18:42:34 -08001634 /* Since small bufs uses blocking writes, a write will be blocked
1635 for the default max poll time (20s) in the event of an SSR.
1636 Reduce the poll time to observe and deal with SSR faster.
1637 */
1638 if (out->use_small_bufs) {
1639 compress_set_max_poll_wait(out->compr, 1000);
1640 }
1641
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001642 audio_extn_dts_create_state_notifier_node(out->usecase);
1643 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1644 popcount(out->channel_mask),
1645 out->playback_started);
1646
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001647#ifdef DS1_DOLBY_DDP_ENABLED
1648 if (audio_extn_is_dolby_format(out->format))
1649 audio_extn_dolby_send_ddp_endp_params(adev);
1650#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001651 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1652 if (adev->visualizer_start_output != NULL)
1653 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1654 if (adev->offload_effects_start_output != NULL)
1655 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001656 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 }
Eric Laurent994a6932013-07-17 11:51:42 -07001659 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001661error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001663error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001664 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665}
1666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667static int check_input_parameters(uint32_t sample_rate,
1668 audio_format_t format,
1669 int channel_count)
1670{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001671 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001673 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001674 !voice_extn_compress_voip_is_format_supported(format) &&
1675 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001676
1677 switch (channel_count) {
1678 case 1:
1679 case 2:
1680 case 6:
1681 break;
1682 default:
1683 ret = -EINVAL;
1684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685
1686 switch (sample_rate) {
1687 case 8000:
1688 case 11025:
1689 case 12000:
1690 case 16000:
1691 case 22050:
1692 case 24000:
1693 case 32000:
1694 case 44100:
1695 case 48000:
1696 break;
1697 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001698 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 }
1700
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001701 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702}
1703
1704static size_t get_input_buffer_size(uint32_t sample_rate,
1705 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001706 int channel_count,
1707 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708{
1709 size_t size = 0;
1710
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001711 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1712 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001714 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001715 if (is_low_latency)
1716 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001717 /* ToDo: should use frame_size computed based on the format and
1718 channel_count here. */
1719 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001721 /* make sure the size is multiple of 32 bytes
1722 * At 48 kHz mono 16-bit PCM:
1723 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1724 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1725 */
1726 size += 0x1f;
1727 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001728
1729 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730}
1731
1732static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1733{
1734 struct stream_out *out = (struct stream_out *)stream;
1735
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001736 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737}
1738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001739static int out_set_sample_rate(struct audio_stream *stream __unused,
1740 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741{
1742 return -ENOSYS;
1743}
1744
1745static size_t out_get_buffer_size(const struct audio_stream *stream)
1746{
1747 struct stream_out *out = (struct stream_out *)stream;
1748
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001749 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001751 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1752 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001754 return out->config.period_size *
1755 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756}
1757
1758static uint32_t out_get_channels(const struct audio_stream *stream)
1759{
1760 struct stream_out *out = (struct stream_out *)stream;
1761
1762 return out->channel_mask;
1763}
1764
1765static audio_format_t out_get_format(const struct audio_stream *stream)
1766{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 struct stream_out *out = (struct stream_out *)stream;
1768
1769 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770}
1771
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001772static int out_set_format(struct audio_stream *stream __unused,
1773 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774{
1775 return -ENOSYS;
1776}
1777
1778static int out_standby(struct audio_stream *stream)
1779{
1780 struct stream_out *out = (struct stream_out *)stream;
1781 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301783 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1784 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001785 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1786 /* Ignore standby in case of voip call because the voip output
1787 * stream is closed in adev_close_output_stream()
1788 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301789 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001790 return 0;
1791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001795 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001797 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 if (out->pcm) {
1799 pcm_close(out->pcm);
1800 out->pcm = NULL;
1801 }
1802 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001803 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 out->gapless_mdata.encoder_delay = 0;
1806 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->compr != NULL) {
1808 compress_close(out->compr);
1809 out->compr = NULL;
1810 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001813 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 }
1815 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001816 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 return 0;
1818}
1819
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001820static int out_dump(const struct audio_stream *stream __unused,
1821 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822{
1823 return 0;
1824}
1825
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1827{
1828 int ret = 0;
1829 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001830 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001831
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001833 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 return -EINVAL;
1835 }
1836
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1838 if (ret >= 0) {
1839 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1840 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1841 ALOGV("ADTS format is set in offload mode");
1842 }
1843 out->send_new_metadata = 1;
1844 }
1845
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301846 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001847
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001848 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1849 if(ret >= 0)
1850 is_meta_data_params = true;
1851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301852 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001853 is_meta_data_params = true;
1854 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301855 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001856 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1858 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001859 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301860 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1863 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001864 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301865 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 }
1867
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001868 if(!is_meta_data_params) {
1869 ALOGV("%s: Not gapless meta data params", __func__);
1870 return 0;
1871 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872 out->send_new_metadata = 1;
1873 ALOGV("%s new encoder delay %u and padding %u", __func__,
1874 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1875
1876 return 0;
1877}
1878
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001879static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1880{
1881 return out == adev->primary_output || out == adev->voice_tx_output;
1882}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1885{
1886 struct stream_out *out = (struct stream_out *)stream;
1887 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001888 struct audio_usecase *usecase;
1889 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 struct str_parms *parms;
1891 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001892 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001893 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
sangwoobc677242013-08-08 16:53:43 +09001895 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301898 if (!parms)
1899 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001900 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1901 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001904 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301907 * When HDMI cable is unplugged/usb hs is disconnected the
1908 * music playback is paused and the policy manager sends routing=0
1909 * But the audioflingercontinues to write data until standby time
1910 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 * Avoid this by routing audio to speaker until standby.
1912 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301913 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1914 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001915 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001916 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1917 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 }
1919
1920 /*
1921 * select_devices() call below switches all the usecases on the same
1922 * backend to the new device. Refer to check_usecases_codec_backend() in
1923 * the select_devices(). But how do we undo this?
1924 *
1925 * For example, music playback is active on headset (deep-buffer usecase)
1926 * and if we go to ringtones and select a ringtone, low-latency usecase
1927 * will be started on headset+speaker. As we can't enable headset+speaker
1928 * and headset devices at the same time, select_devices() switches the music
1929 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1930 * So when the ringtone playback is completed, how do we undo the same?
1931 *
1932 * We are relying on the out_set_parameters() call on deep-buffer output,
1933 * once the ringtone playback is ended.
1934 * NOTE: We should not check if the current devices are same as new devices.
1935 * Because select_devices() must be called to switch back the music
1936 * playback to headset.
1937 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001938 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001939 out->devices = val;
1940
1941 if (!out->standby)
1942 select_devices(adev, out->usecase);
1943
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001944 if (output_drives_call(adev, out)) {
1945 if(!voice_is_in_call(adev)) {
1946 if (adev->mode == AUDIO_MODE_IN_CALL) {
1947 adev->current_call_output = out;
1948 ret = voice_start_call(adev);
1949 }
1950 } else {
1951 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001952 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001953 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001954 }
1955 }
1956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001958 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001960
1961 if (out == adev->primary_output) {
1962 pthread_mutex_lock(&adev->lock);
1963 audio_extn_set_parameters(adev, parms);
1964 pthread_mutex_unlock(&adev->lock);
1965 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001966 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001967 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001968 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001969
1970 audio_extn_dts_create_state_notifier_node(out->usecase);
1971 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1972 popcount(out->channel_mask),
1973 out->playback_started);
1974
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001975 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001976 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301979error:
Eric Laurent994a6932013-07-17 11:51:42 -07001980 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 return ret;
1982}
1983
1984static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1985{
1986 struct stream_out *out = (struct stream_out *)stream;
1987 struct str_parms *query = str_parms_create_str(keys);
1988 char *str;
1989 char value[256];
1990 struct str_parms *reply = str_parms_create();
1991 size_t i, j;
1992 int ret;
1993 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001994
1995 if (!query || !reply) {
1996 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1997 return NULL;
1998 }
1999
Eric Laurent994a6932013-07-17 11:51:42 -07002000 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2002 if (ret >= 0) {
2003 value[0] = '\0';
2004 i = 0;
2005 while (out->supported_channel_masks[i] != 0) {
2006 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2007 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2008 if (!first) {
2009 strcat(value, "|");
2010 }
2011 strcat(value, out_channels_name_to_enum_table[j].name);
2012 first = false;
2013 break;
2014 }
2015 }
2016 i++;
2017 }
2018 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2019 str = str_parms_to_str(reply);
2020 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002021 voice_extn_out_get_parameters(out, query, reply);
2022 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002023 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002024 free(str);
2025 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002026 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002028
2029 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2030 if (ret >= 0) {
2031 value[0] = '\0';
2032 i = 0;
2033 first = true;
2034 while (out->supported_formats[i] != 0) {
2035 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2036 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2037 if (!first) {
2038 strcat(value, "|");
2039 }
2040 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2041 first = false;
2042 break;
2043 }
2044 }
2045 i++;
2046 }
2047 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2048 str = str_parms_to_str(reply);
2049 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 str_parms_destroy(query);
2051 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002052 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 return str;
2054}
2055
2056static uint32_t out_get_latency(const struct audio_stream_out *stream)
2057{
2058 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002059 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060
Alexy Josephaa54c872014-12-03 02:46:47 -08002061 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002062 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002063 } else {
2064 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002066 }
2067
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302068 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002069 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070}
2071
2072static int out_set_volume(struct audio_stream_out *stream, float left,
2073 float right)
2074{
Eric Laurenta9024de2013-04-04 09:19:12 -07002075 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 int volume[2];
2077
Eric Laurenta9024de2013-04-04 09:19:12 -07002078 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2079 /* only take left channel into account: the API is for stereo anyway */
2080 out->muted = (left == 0.0f);
2081 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002082 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002083 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2084 /*
2085 * Set mute or umute on HDMI passthrough stream.
2086 * Only take left channel into account.
2087 * Mute is 0 and unmute 1
2088 */
2089 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2090 } else {
2091 char mixer_ctl_name[128];
2092 struct audio_device *adev = out->dev;
2093 struct mixer_ctl *ctl;
2094 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002095 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002097 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2098 "Compress Playback %d Volume", pcm_device_id);
2099 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2100 if (!ctl) {
2101 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2102 __func__, mixer_ctl_name);
2103 return -EINVAL;
2104 }
2105 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2106 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2107 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2108 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002110 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 return -ENOSYS;
2113}
2114
2115static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2116 size_t bytes)
2117{
2118 struct stream_out *out = (struct stream_out *)stream;
2119 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302120 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002121 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302124
Naresh Tanniru80659832014-06-04 18:17:56 +05302125 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002126 // increase written size during SSR to avoid mismatch
2127 // with the written frames count in AF
2128 if (!is_offload_usecase(out->usecase))
2129 out->written += bytes / (out->config.channels * sizeof(short));
2130
Naresh Tanniru80659832014-06-04 18:17:56 +05302131 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302132 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302133 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302134 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002135 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302136 //during SSR for compress usecase we should return error to flinger
2137 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2138 pthread_mutex_unlock(&out->lock);
2139 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302140 }
2141 }
2142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002144 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002145 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002146 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2147 ret = voice_extn_compress_voip_start_output_stream(out);
2148 else
2149 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002150 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002153 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 goto exit;
2155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002158 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002159 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002161 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2163 out->send_new_metadata = 0;
2164 }
2165
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302167 if (ret < 0)
2168 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002169 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002170 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302171 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302173 } else if (-ENETRESET == ret) {
2174 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2175 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2176 pthread_mutex_unlock(&out->lock);
2177 out_standby(&out->stream.common);
2178 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302180 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002182 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 out->playback_started = 1;
2184 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002185
2186 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2187 popcount(out->channel_mask),
2188 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 }
2190 pthread_mutex_unlock(&out->lock);
2191 return ret;
2192 } else {
2193 if (out->pcm) {
2194 if (out->muted)
2195 memset((void *)buffer, 0, bytes);
2196 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002197 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2198 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2199 else
2200 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302201 if (ret < 0)
2202 ret = -errno;
2203 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002204 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206 }
2207
2208exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302209 /* ToDo: There may be a corner case when SSR happens back to back during
2210 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302211 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302212 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302213 }
2214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 pthread_mutex_unlock(&out->lock);
2216
2217 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002218 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002219 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302220 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302221 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302222 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302223 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302224 out->standby = true;
2225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002227 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302228 out_get_sample_rate(&out->stream.common));
2229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 }
2231 return bytes;
2232}
2233
2234static int out_get_render_position(const struct audio_stream_out *stream,
2235 uint32_t *dsp_frames)
2236{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302238 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002239
2240 if (dsp_frames == NULL)
2241 return -EINVAL;
2242
2243 *dsp_frames = 0;
2244 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002245 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 pthread_mutex_lock(&out->lock);
2247 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302248 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302250 if (ret < 0)
2251 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 ALOGVV("%s rendered frames %d sample_rate %d",
2253 __func__, *dsp_frames, out->sample_rate);
2254 }
2255 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302256 if (-ENETRESET == ret) {
2257 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2258 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2259 return -EINVAL;
2260 } else if(ret < 0) {
2261 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2262 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302263 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2264 /*
2265 * Handle corner case where compress session is closed during SSR
2266 * and timestamp is queried
2267 */
2268 ALOGE(" ERROR: sound card not active, return error");
2269 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302270 } else {
2271 return 0;
2272 }
Zhou Song32a556e2015-05-05 10:46:56 +08002273 } else if (audio_is_linear_pcm(out->format)) {
2274 *dsp_frames = out->written;
2275 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 } else
2277 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278}
2279
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002280static int out_add_audio_effect(const struct audio_stream *stream __unused,
2281 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282{
2283 return 0;
2284}
2285
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002286static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2287 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288{
2289 return 0;
2290}
2291
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002292static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2293 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294{
2295 return -EINVAL;
2296}
2297
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002298static int out_get_presentation_position(const struct audio_stream_out *stream,
2299 uint64_t *frames, struct timespec *timestamp)
2300{
2301 struct stream_out *out = (struct stream_out *)stream;
2302 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002303 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002304
2305 pthread_mutex_lock(&out->lock);
2306
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002307 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002308 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302309 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002310 &out->sample_rate);
2311 ALOGVV("%s rendered frames %ld sample_rate %d",
2312 __func__, dsp_frames, out->sample_rate);
2313 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302314 if (ret < 0)
2315 ret = -errno;
2316 if (-ENETRESET == ret) {
2317 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2318 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2319 ret = -EINVAL;
2320 } else
2321 ret = 0;
2322
Eric Laurent949a0892013-09-20 09:20:13 -07002323 /* this is the best we can do */
2324 clock_gettime(CLOCK_MONOTONIC, timestamp);
2325 }
2326 } else {
2327 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002328 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002329 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2330 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002331 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002332 // This adjustment accounts for buffering after app processor.
2333 // It is based on estimated DSP latency per use case, rather than exact.
2334 signed_frames -=
2335 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2336
Eric Laurent949a0892013-09-20 09:20:13 -07002337 // It would be unusual for this value to be negative, but check just in case ...
2338 if (signed_frames >= 0) {
2339 *frames = signed_frames;
2340 ret = 0;
2341 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002342 }
2343 }
2344 }
2345
2346 pthread_mutex_unlock(&out->lock);
2347
2348 return ret;
2349}
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351static int out_set_callback(struct audio_stream_out *stream,
2352 stream_callback_t callback, void *cookie)
2353{
2354 struct stream_out *out = (struct stream_out *)stream;
2355
2356 ALOGV("%s", __func__);
2357 pthread_mutex_lock(&out->lock);
2358 out->offload_callback = callback;
2359 out->offload_cookie = cookie;
2360 pthread_mutex_unlock(&out->lock);
2361 return 0;
2362}
2363
2364static int out_pause(struct audio_stream_out* stream)
2365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367 int status = -ENOSYS;
2368 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002369 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002370 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 pthread_mutex_lock(&out->lock);
2372 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302373 struct audio_device *adev = out->dev;
2374 int snd_scard_state = get_snd_card_state(adev);
2375
2376 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2377 status = compress_pause(out->compr);
2378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002380
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302381 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002382 audio_extn_dts_notify_playback_state(out->usecase, 0,
2383 out->sample_rate, popcount(out->channel_mask),
2384 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 }
2386 pthread_mutex_unlock(&out->lock);
2387 }
2388 return status;
2389}
2390
2391static int out_resume(struct audio_stream_out* stream)
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 int status = -ENOSYS;
2395 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002396 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002397 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 status = 0;
2399 pthread_mutex_lock(&out->lock);
2400 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302401 struct audio_device *adev = out->dev;
2402 int snd_scard_state = get_snd_card_state(adev);
2403
2404 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2405 status = compress_resume(out->compr);
2406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002407 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002408
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302409 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002410 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2411 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 }
2413 pthread_mutex_unlock(&out->lock);
2414 }
2415 return status;
2416}
2417
2418static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2419{
2420 struct stream_out *out = (struct stream_out *)stream;
2421 int status = -ENOSYS;
2422 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002423 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 pthread_mutex_lock(&out->lock);
2425 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2426 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2427 else
2428 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2429 pthread_mutex_unlock(&out->lock);
2430 }
2431 return status;
2432}
2433
2434static int out_flush(struct audio_stream_out* stream)
2435{
2436 struct stream_out *out = (struct stream_out *)stream;
2437 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002438 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002439 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 pthread_mutex_lock(&out->lock);
2441 stop_compressed_output_l(out);
2442 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002443 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444 return 0;
2445 }
2446 return -ENOSYS;
2447}
2448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449/** audio_stream_in implementation **/
2450static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2451{
2452 struct stream_in *in = (struct stream_in *)stream;
2453
2454 return in->config.rate;
2455}
2456
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002457static int in_set_sample_rate(struct audio_stream *stream __unused,
2458 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459{
2460 return -ENOSYS;
2461}
2462
2463static size_t in_get_buffer_size(const struct audio_stream *stream)
2464{
2465 struct stream_in *in = (struct stream_in *)stream;
2466
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002467 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2468 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002469 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2470 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002471
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002472 return in->config.period_size *
2473 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474}
2475
2476static uint32_t in_get_channels(const struct audio_stream *stream)
2477{
2478 struct stream_in *in = (struct stream_in *)stream;
2479
2480 return in->channel_mask;
2481}
2482
2483static audio_format_t in_get_format(const struct audio_stream *stream)
2484{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002485 struct stream_in *in = (struct stream_in *)stream;
2486
2487 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488}
2489
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002490static int in_set_format(struct audio_stream *stream __unused,
2491 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492{
2493 return -ENOSYS;
2494}
2495
2496static int in_standby(struct audio_stream *stream)
2497{
2498 struct stream_in *in = (struct stream_in *)stream;
2499 struct audio_device *adev = in->dev;
2500 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302501 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2502 stream, in->usecase, use_case_table[in->usecase]);
2503
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002504 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2505 /* Ignore standby in case of voip call because the voip input
2506 * stream is closed in adev_close_input_stream()
2507 */
2508 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2509 return status;
2510 }
2511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002513 if (!in->standby && in->is_st_session) {
2514 ALOGD("%s: sound trigger pcm stop lab", __func__);
2515 audio_extn_sound_trigger_stop_lab(in);
2516 in->standby = 1;
2517 }
2518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002520 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002522 if (in->pcm) {
2523 pcm_close(in->pcm);
2524 in->pcm = NULL;
2525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002527 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 }
2529 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002530 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 return status;
2532}
2533
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002534static int in_dump(const struct audio_stream *stream __unused,
2535 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536{
2537 return 0;
2538}
2539
2540static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2541{
2542 struct stream_in *in = (struct stream_in *)stream;
2543 struct audio_device *adev = in->dev;
2544 struct str_parms *parms;
2545 char *str;
2546 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002547 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302549 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 parms = str_parms_create_str(kvpairs);
2551
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302552 if (!parms)
2553 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002556
2557 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2558 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 val = atoi(value);
2560 /* no audio source uses val == 0 */
2561 if ((in->source != val) && (val != 0)) {
2562 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002563 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2564 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2565 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2566 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002567 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002568 err = voice_extn_compress_voip_open_input_stream(in);
2569 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002570 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002571 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002572 }
2573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 }
2575 }
2576
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002577 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2578 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002580 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581 in->device = val;
2582 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002583 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002584 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 }
2586 }
2587
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002588done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002590 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591
2592 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302593error:
Eric Laurent994a6932013-07-17 11:51:42 -07002594 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 return ret;
2596}
2597
2598static char* in_get_parameters(const struct audio_stream *stream,
2599 const char *keys)
2600{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002601 struct stream_in *in = (struct stream_in *)stream;
2602 struct str_parms *query = str_parms_create_str(keys);
2603 char *str;
2604 char value[256];
2605 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002606
2607 if (!query || !reply) {
2608 ALOGE("in_get_parameters: failed to create query or reply");
2609 return NULL;
2610 }
2611
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002612 ALOGV("%s: enter: keys - %s", __func__, keys);
2613
2614 voice_extn_in_get_parameters(in, query, reply);
2615
2616 str = str_parms_to_str(reply);
2617 str_parms_destroy(query);
2618 str_parms_destroy(reply);
2619
2620 ALOGV("%s: exit: returns - %s", __func__, str);
2621 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622}
2623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002624static int in_set_gain(struct audio_stream_in *stream __unused,
2625 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626{
2627 return 0;
2628}
2629
2630static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2631 size_t bytes)
2632{
2633 struct stream_in *in = (struct stream_in *)stream;
2634 struct audio_device *adev = in->dev;
2635 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302636 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302639
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002640 if (in->is_st_session) {
2641 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2642 /* Read from sound trigger HAL */
2643 audio_extn_sound_trigger_read(in, buffer, bytes);
2644 pthread_mutex_unlock(&in->lock);
2645 return bytes;
2646 }
2647
2648 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2649 ALOGD(" %s: sound card is not active/SSR state", __func__);
2650 ret= -EIO;;
2651 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302652 }
2653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002655 pthread_mutex_lock(&adev->lock);
2656 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2657 ret = voice_extn_compress_voip_start_input_stream(in);
2658 else
2659 ret = start_input_stream(in);
2660 pthread_mutex_unlock(&adev->lock);
2661 if (ret != 0) {
2662 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 }
2664 in->standby = 0;
2665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666
2667 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002668 if (audio_extn_ssr_get_enabled() &&
2669 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002670 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002671 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2672 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002673 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2674 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002675 else
2676 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302677 if (ret < 0)
2678 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 }
2680
2681 /*
2682 * Instead of writing zeroes here, we could trust the hardware
2683 * to always provide zeroes when muted.
2684 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302685 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2686 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 memset(buffer, 0, bytes);
2688
2689exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302690 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302691 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002692 if (-ENETRESET == ret)
2693 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 pthread_mutex_unlock(&in->lock);
2696
2697 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302698 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302699 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302700 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302701 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302702 in->standby = true;
2703 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302704 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002706 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002707 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302708 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 }
2710 return bytes;
2711}
2712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002713static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714{
2715 return 0;
2716}
2717
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002718static int add_remove_audio_effect(const struct audio_stream *stream,
2719 effect_handle_t effect,
2720 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002722 struct stream_in *in = (struct stream_in *)stream;
2723 int status = 0;
2724 effect_descriptor_t desc;
2725
2726 status = (*effect)->get_descriptor(effect, &desc);
2727 if (status != 0)
2728 return status;
2729
2730 pthread_mutex_lock(&in->lock);
2731 pthread_mutex_lock(&in->dev->lock);
2732 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2733 in->enable_aec != enable &&
2734 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2735 in->enable_aec = enable;
2736 if (!in->standby)
2737 select_devices(in->dev, in->usecase);
2738 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002739 if (in->enable_ns != enable &&
2740 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2741 in->enable_ns = enable;
2742 if (!in->standby)
2743 select_devices(in->dev, in->usecase);
2744 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002745 pthread_mutex_unlock(&in->dev->lock);
2746 pthread_mutex_unlock(&in->lock);
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 return 0;
2749}
2750
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002751static int in_add_audio_effect(const struct audio_stream *stream,
2752 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753{
Eric Laurent994a6932013-07-17 11:51:42 -07002754 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002755 return add_remove_audio_effect(stream, effect, true);
2756}
2757
2758static int in_remove_audio_effect(const struct audio_stream *stream,
2759 effect_handle_t effect)
2760{
Eric Laurent994a6932013-07-17 11:51:42 -07002761 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002762 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763}
2764
2765static int adev_open_output_stream(struct audio_hw_device *dev,
2766 audio_io_handle_t handle,
2767 audio_devices_t devices,
2768 audio_output_flags_t flags,
2769 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002770 struct audio_stream_out **stream_out,
2771 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772{
2773 struct audio_device *adev = (struct audio_device *)dev;
2774 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002775 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002776 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302779
2780 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2781 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002782 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302783 return -EINVAL;
2784 }
2785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2787
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302788 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2789 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2790 devices, flags, &out->stream);
2791
2792
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002793 if (!out) {
2794 return -ENOMEM;
2795 }
2796
Haynes Mathew George204045b2015-02-25 20:32:03 -08002797 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2798 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 if (devices == AUDIO_DEVICE_NONE)
2801 devices = AUDIO_DEVICE_OUT_SPEAKER;
2802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 out->flags = flags;
2804 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002805 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002806 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 out->sample_rate = config->sample_rate;
2808 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2809 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002810 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002811 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002812 out->non_blocking = 0;
2813 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814
2815 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002816 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2817 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002818 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2819 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2820
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002821 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002822 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2823 ret = read_hdmi_channel_masks(out);
2824
2825 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2826 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002827 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002828 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002829 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002830
2831 if (config->sample_rate == 0)
2832 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2833 if (config->channel_mask == 0)
2834 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2835
2836 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2839 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002841 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002843 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2844 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002845 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002846 ret = voice_extn_compress_voip_open_output_stream(out);
2847 if (ret != 0) {
2848 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2849 __func__, ret);
2850 goto error_open;
2851 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002852 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2853 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2854
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2856 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2857 ALOGE("%s: Unsupported Offload information", __func__);
2858 ret = -EINVAL;
2859 goto error_open;
2860 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002861
2862 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2863 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2864 ALOGV("read and update_pass through formats");
2865 ret = audio_extn_dolby_update_passt_formats(adev, out);
2866 if(ret != 0) {
2867 goto error_open;
2868 }
2869 if(config->offload_info.format == 0)
2870 config->offload_info.format = out->supported_formats[0];
2871 }
2872
Mingming Yin90310102013-11-13 16:57:00 -08002873 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002874 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002875 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 ret = -EINVAL;
2877 goto error_open;
2878 }
2879
2880 out->compr_config.codec = (struct snd_codec *)
2881 calloc(1, sizeof(struct snd_codec));
2882
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002883 if (!out->compr_config.codec) {
2884 ret = -ENOMEM;
2885 goto error_open;
2886 }
2887
vivek mehta0ea887a2015-08-26 14:01:20 -07002888 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2889 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2890 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2891 } else {
2892 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2893 out->usecase = get_offload_usecase(adev);
2894 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 if (config->offload_info.channel_mask)
2896 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002897 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 config->offload_info.channel_mask = config->channel_mask;
2900 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002901 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 out->sample_rate = config->offload_info.sample_rate;
2903
2904 out->stream.set_callback = out_set_callback;
2905 out->stream.pause = out_pause;
2906 out->stream.resume = out_resume;
2907 out->stream.drain = out_drain;
2908 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002909 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002911 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002912 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002913 audio_extn_dolby_get_snd_codec_id(adev, out,
2914 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002915 else
2916 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002918
2919 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2920 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002921 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002922 platform_get_pcm_offload_buffer_size(&config->offload_info);
2923 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2924 out->compr_config.fragment_size =
2925 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002926 } else {
2927 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002928 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2931 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002932 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 out->compr_config.codec->bit_rate =
2934 config->offload_info.bit_rate;
2935 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002936 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002937 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302938 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002939 /*TODO: Do we need to change it for passthrough */
2940 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941
Mingming Yin3ee55c62014-08-04 14:23:35 -07002942 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2943 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002944 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2945 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002946 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002947 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002948 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2949 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002950
Mingming Yin3ee55c62014-08-04 14:23:35 -07002951 if (out->bit_width == 24) {
2952 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2953 }
2954
Amit Shekhar6f461b12014-08-01 14:52:58 -07002955 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302956 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2959 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002960
Mingming Yin497419f2015-07-01 16:57:32 -07002961 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002962 //this flag is set from framework only if its for PCM formats
2963 //no need to check for PCM format again
2964 out->non_blocking = 0;
2965 out->use_small_bufs = true;
2966 ALOGI("Keep write blocking for small buff: non_blockling %d",
2967 out->non_blocking);
2968 }
2969
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002970 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002971 out->offload_state = OFFLOAD_STATE_IDLE;
2972 out->playback_started = 0;
2973
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002974 audio_extn_dts_create_state_notifier_node(out->usecase);
2975
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002976 create_offload_callback_thread(out);
2977 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2978 __func__, config->offload_info.version,
2979 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002980 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002981 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002982 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2983 ret = voice_check_and_set_incall_music_usecase(adev, out);
2984 if (ret != 0) {
2985 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2986 __func__, ret);
2987 goto error_open;
2988 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002989 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2990 if (config->sample_rate == 0)
2991 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2992 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2993 config->sample_rate != 8000) {
2994 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2995 ret = -EINVAL;
2996 goto error_open;
2997 }
2998 out->sample_rate = config->sample_rate;
2999 out->config.rate = config->sample_rate;
3000 if (config->format == AUDIO_FORMAT_DEFAULT)
3001 config->format = AUDIO_FORMAT_PCM_16_BIT;
3002 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3003 config->format = AUDIO_FORMAT_PCM_16_BIT;
3004 ret = -EINVAL;
3005 goto error_open;
3006 }
3007 out->format = config->format;
3008 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3009 out->config = pcm_config_afe_proxy_playback;
3010 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003011 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003012 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3014 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003015 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003016 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3017 format = AUDIO_FORMAT_PCM_16_BIT;
3018 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3019 out->config = pcm_config_deep_buffer;
3020 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003021 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003022 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003023 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003024 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003025 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003026 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 }
3028
Amit Shekhar1d896042014-10-03 13:16:09 -07003029 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3030 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003031 /* TODO remove this hardcoding and check why width is zero*/
3032 if (out->bit_width == 0)
3033 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003034 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3035 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003036 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003037 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003038 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3039 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3040 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003041 if(adev->primary_output == NULL)
3042 adev->primary_output = out;
3043 else {
3044 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003045 ret = -EEXIST;
3046 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003047 }
3048 }
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 /* Check if this usecase is already existing */
3051 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003052 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3053 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003056 ret = -EEXIST;
3057 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 }
3059 pthread_mutex_unlock(&adev->lock);
3060
3061 out->stream.common.get_sample_rate = out_get_sample_rate;
3062 out->stream.common.set_sample_rate = out_set_sample_rate;
3063 out->stream.common.get_buffer_size = out_get_buffer_size;
3064 out->stream.common.get_channels = out_get_channels;
3065 out->stream.common.get_format = out_get_format;
3066 out->stream.common.set_format = out_set_format;
3067 out->stream.common.standby = out_standby;
3068 out->stream.common.dump = out_dump;
3069 out->stream.common.set_parameters = out_set_parameters;
3070 out->stream.common.get_parameters = out_get_parameters;
3071 out->stream.common.add_audio_effect = out_add_audio_effect;
3072 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3073 out->stream.get_latency = out_get_latency;
3074 out->stream.set_volume = out_set_volume;
3075 out->stream.write = out_write;
3076 out->stream.get_render_position = out_get_render_position;
3077 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003078 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003081 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003082 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083
3084 config->format = out->stream.common.get_format(&out->stream.common);
3085 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3086 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3087
3088 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303089 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003090 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003091
3092 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3093 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3094 popcount(out->channel_mask), out->playback_started);
3095
Eric Laurent994a6932013-07-17 11:51:42 -07003096 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003098
3099error_open:
3100 free(out);
3101 *stream_out = NULL;
3102 ALOGD("%s: exit: ret %d", __func__, ret);
3103 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104}
3105
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003106static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 struct audio_stream_out *stream)
3108{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 struct stream_out *out = (struct stream_out *)stream;
3110 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003111 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303113 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3114
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003115 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303116 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003117 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303118 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003119 if(ret != 0)
3120 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3121 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003122 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003123 out_standby(&stream->common);
3124
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003126 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003128 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 if (out->compr_config.codec != NULL)
3130 free(out->compr_config.codec);
3131 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003132
3133 if (adev->voice_tx_output == out)
3134 adev->voice_tx_output = NULL;
3135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 pthread_cond_destroy(&out->cond);
3137 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003139 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140}
3141
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003142static void close_compress_sessions(struct audio_device *adev)
3143{
Mingming Yin7b762e72015-03-04 13:47:32 -08003144 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303145 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003146 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003147 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303148
3149 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003150 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303151 if (is_offload_usecase(usecase->id)) {
3152 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003153 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3154 out = usecase->stream.out;
3155 pthread_mutex_unlock(&adev->lock);
3156 out_standby(&out->stream.common);
3157 pthread_mutex_lock(&adev->lock);
3158 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303159 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003160 }
3161 pthread_mutex_unlock(&adev->lock);
3162}
3163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3165{
3166 struct audio_device *adev = (struct audio_device *)dev;
3167 struct str_parms *parms;
3168 char *str;
3169 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003170 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 int ret;
3172 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003174 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303177 if (!parms)
3178 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3180 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303181 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303182 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303183 struct listnode *node;
3184 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303185 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303186 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003187 //close compress sessions on OFFLINE status
3188 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303189 } else if (strstr(snd_card_status, "ONLINE")) {
3190 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303191 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003192 //send dts hpx license if enabled
3193 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303194 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303195 }
3196
3197 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 status = voice_set_parameters(adev, parms);
3199 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003200 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003202 status = platform_set_parameters(adev->platform, parms);
3203 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003204 goto done;
3205
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3207 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003208 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3210 adev->bluetooth_nrec = true;
3211 else
3212 adev->bluetooth_nrec = false;
3213 }
3214
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003215 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3216 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3218 adev->screen_off = false;
3219 else
3220 adev->screen_off = true;
3221 }
3222
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003223 ret = str_parms_get_int(parms, "rotation", &val);
3224 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003225 bool reverse_speakers = false;
3226 switch(val) {
3227 // FIXME: note that the code below assumes that the speakers are in the correct placement
3228 // relative to the user when the device is rotated 90deg from its default rotation. This
3229 // assumption is device-specific, not platform-specific like this code.
3230 case 270:
3231 reverse_speakers = true;
3232 break;
3233 case 0:
3234 case 90:
3235 case 180:
3236 break;
3237 default:
3238 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003239 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003240 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003241 if (status == 0) {
3242 if (adev->speaker_lr_swap != reverse_speakers) {
3243 adev->speaker_lr_swap = reverse_speakers;
3244 // only update the selected device if there is active pcm playback
3245 struct audio_usecase *usecase;
3246 struct listnode *node;
3247 list_for_each(node, &adev->usecase_list) {
3248 usecase = node_to_item(node, struct audio_usecase, list);
3249 if (usecase->type == PCM_PLAYBACK) {
3250 select_devices(adev, usecase->id);
3251 break;
3252 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003253 }
3254 }
3255 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003256 }
3257
Mingming Yin514a8bc2014-07-29 15:22:21 -07003258 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3259 if (ret >= 0) {
3260 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3261 adev->bt_wb_speech_enabled = true;
3262 else
3263 adev->bt_wb_speech_enabled = false;
3264 }
3265
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003266 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3267 if (ret >= 0) {
3268 val = atoi(value);
3269 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3270 ALOGV("cache new edid");
3271 platform_cache_edid(adev->platform);
3272 }
3273 }
3274
3275 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3276 if (ret >= 0) {
3277 val = atoi(value);
3278 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3279 ALOGV("invalidate cached edid");
3280 platform_invalidate_edid(adev->platform);
3281 }
3282 }
3283
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003284 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003285
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003286done:
3287 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003288 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303289error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003290 ALOGV("%s: exit with code(%d)", __func__, status);
3291 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292}
3293
3294static char* adev_get_parameters(const struct audio_hw_device *dev,
3295 const char *keys)
3296{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003297 struct audio_device *adev = (struct audio_device *)dev;
3298 struct str_parms *reply = str_parms_create();
3299 struct str_parms *query = str_parms_create_str(keys);
3300 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303301 char value[256] = {0};
3302 int ret = 0;
3303
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003304 if (!query || !reply) {
3305 ALOGE("adev_get_parameters: failed to create query or reply");
3306 return NULL;
3307 }
3308
Naresh Tannirud7205b62014-06-20 02:54:48 +05303309 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3310 sizeof(value));
3311 if (ret >=0) {
3312 int val = 1;
3313 pthread_mutex_lock(&adev->snd_card_status.lock);
3314 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3315 val = 0;
3316 pthread_mutex_unlock(&adev->snd_card_status.lock);
3317 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3318 goto exit;
3319 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003320
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003321 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003322 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003323 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003324 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303325 pthread_mutex_unlock(&adev->lock);
3326
Naresh Tannirud7205b62014-06-20 02:54:48 +05303327exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003328 str = str_parms_to_str(reply);
3329 str_parms_destroy(query);
3330 str_parms_destroy(reply);
3331
3332 ALOGV("%s: exit: returns - %s", __func__, str);
3333 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return 0;
3339}
3340
3341static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3342{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003343 int ret;
3344 struct audio_device *adev = (struct audio_device *)dev;
3345 pthread_mutex_lock(&adev->lock);
3346 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003347 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003348 pthread_mutex_unlock(&adev->lock);
3349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350}
3351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003352static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3353 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354{
3355 return -ENOSYS;
3356}
3357
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003358static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3359 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360{
3361 return -ENOSYS;
3362}
3363
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003364static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3365 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366{
3367 return -ENOSYS;
3368}
3369
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003370static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3371 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372{
3373 return -ENOSYS;
3374}
3375
3376static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3377{
3378 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 pthread_mutex_lock(&adev->lock);
3381 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003382 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003384 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3385 voice_is_in_call(adev)) {
3386 voice_stop_call(adev);
3387 adev->current_call_output = NULL;
3388 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 }
3390 pthread_mutex_unlock(&adev->lock);
3391 return 0;
3392}
3393
3394static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3395{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003396 int ret;
3397
3398 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003399 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003400 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3401 pthread_mutex_unlock(&adev->lock);
3402
3403 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404}
3405
3406static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3407{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003408 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 return 0;
3410}
3411
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003412static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 const struct audio_config *config)
3414{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003415 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003417 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3418 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419}
3420
3421static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003422 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 audio_devices_t devices,
3424 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003425 struct audio_stream_in **stream_in,
3426 audio_input_flags_t flags __unused,
3427 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003428 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429{
3430 struct audio_device *adev = (struct audio_device *)dev;
3431 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003432 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003433 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003434 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 *stream_in = NULL;
3437 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3438 return -EINVAL;
3439
3440 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003441
3442 if (!in) {
3443 ALOGE("failed to allocate input stream");
3444 return -ENOMEM;
3445 }
3446
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303447 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003448 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3449 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003451 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->stream.common.get_sample_rate = in_get_sample_rate;
3454 in->stream.common.set_sample_rate = in_set_sample_rate;
3455 in->stream.common.get_buffer_size = in_get_buffer_size;
3456 in->stream.common.get_channels = in_get_channels;
3457 in->stream.common.get_format = in_get_format;
3458 in->stream.common.set_format = in_set_format;
3459 in->stream.common.standby = in_standby;
3460 in->stream.common.dump = in_dump;
3461 in->stream.common.set_parameters = in_set_parameters;
3462 in->stream.common.get_parameters = in_get_parameters;
3463 in->stream.common.add_audio_effect = in_add_audio_effect;
3464 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3465 in->stream.set_gain = in_set_gain;
3466 in->stream.read = in_read;
3467 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3468
3469 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003470 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 in->standby = 1;
3473 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003474 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
3476 /* Update config params with the requested sample rate and channels */
3477 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003478 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3479 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3480 is_low_latency = true;
3481#if LOW_LATENCY_CAPTURE_USE_CASE
3482 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3483#endif
3484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003487 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003489 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303490 if (adev->mode != AUDIO_MODE_IN_CALL) {
3491 ret = -EINVAL;
3492 goto err_open;
3493 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003494 if (config->sample_rate == 0)
3495 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3496 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3497 config->sample_rate != 8000) {
3498 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3499 ret = -EINVAL;
3500 goto err_open;
3501 }
3502 if (config->format == AUDIO_FORMAT_DEFAULT)
3503 config->format = AUDIO_FORMAT_PCM_16_BIT;
3504 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3505 config->format = AUDIO_FORMAT_PCM_16_BIT;
3506 ret = -EINVAL;
3507 goto err_open;
3508 }
3509
3510 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3511 in->config = pcm_config_afe_proxy_record;
3512 in->config.channels = channel_count;
3513 in->config.rate = config->sample_rate;
3514 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003515 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003516 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003517 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3518 ret = -EINVAL;
3519 goto err_open;
3520 }
3521 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003522 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003523 }
Mingming Yine62d7842013-10-25 16:26:03 -07003524 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003525 audio_extn_compr_cap_format_supported(config->format) &&
3526 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003527 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003528 } else {
3529 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003530 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003531 buffer_size = get_input_buffer_size(config->sample_rate,
3532 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003533 channel_count,
3534 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003535 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003536 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3537 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3538 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3539 (in->config.rate == 8000 || in->config.rate == 16000) &&
3540 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3541 voice_extn_compress_voip_open_input_stream(in);
3542 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003545 /* This stream could be for sound trigger lab,
3546 get sound trigger pcm if present */
3547 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303548 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003551 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003552 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
3554err_open:
3555 free(in);
3556 *stream_in = NULL;
3557 return ret;
3558}
3559
3560static void adev_close_input_stream(struct audio_hw_device *dev,
3561 struct audio_stream_in *stream)
3562{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003563 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003564 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003565 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303566
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303567 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003568
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303569 /* Disable echo reference while closing input stream */
3570 platform_set_echo_reference(adev->platform, false);
3571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003572 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303573 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003574 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303575 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003576 if (ret != 0)
3577 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3578 __func__, ret);
3579 } else
3580 in_standby(&stream->common);
3581
Mingming Yin7b762e72015-03-04 13:47:32 -08003582 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003583 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003584 audio_extn_ssr_deinit();
3585 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586
Mingming Yine62d7842013-10-25 16:26:03 -07003587 if(audio_extn_compr_cap_enabled() &&
3588 audio_extn_compr_cap_format_supported(in->config.format))
3589 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003590
3591 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 return;
3593}
3594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003595static int adev_dump(const audio_hw_device_t *device __unused,
3596 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597{
3598 return 0;
3599}
3600
3601static int adev_close(hw_device_t *device)
3602{
3603 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003604
3605 if (!adev)
3606 return 0;
3607
3608 pthread_mutex_lock(&adev_init_lock);
3609
3610 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003611 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003612 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003613 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003614 audio_route_free(adev->audio_route);
3615 free(adev->snd_dev_ref_cnt);
3616 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003617 free(device);
3618 adev = NULL;
3619 }
3620 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 return 0;
3622}
3623
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003624/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3625 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3626 * just that it _might_ work.
3627 */
3628static int period_size_is_plausible_for_low_latency(int period_size)
3629{
3630 switch (period_size) {
3631 case 160:
3632 case 240:
3633 case 320:
3634 case 480:
3635 return 1;
3636 default:
3637 return 0;
3638 }
3639}
3640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641static int adev_open(const hw_module_t *module, const char *name,
3642 hw_device_t **device)
3643{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003644 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003646 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3648
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003649 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003650 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003651 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003652 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003653 ALOGD("%s: returning existing instance of adev", __func__);
3654 ALOGD("%s: exit", __func__);
3655 pthread_mutex_unlock(&adev_init_lock);
3656 return 0;
3657 }
3658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 adev = calloc(1, sizeof(struct audio_device));
3660
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003661 if (!adev) {
3662 pthread_mutex_unlock(&adev_init_lock);
3663 return -ENOMEM;
3664 }
3665
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003666 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3669 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3670 adev->device.common.module = (struct hw_module_t *)module;
3671 adev->device.common.close = adev_close;
3672
3673 adev->device.init_check = adev_init_check;
3674 adev->device.set_voice_volume = adev_set_voice_volume;
3675 adev->device.set_master_volume = adev_set_master_volume;
3676 adev->device.get_master_volume = adev_get_master_volume;
3677 adev->device.set_master_mute = adev_set_master_mute;
3678 adev->device.get_master_mute = adev_get_master_mute;
3679 adev->device.set_mode = adev_set_mode;
3680 adev->device.set_mic_mute = adev_set_mic_mute;
3681 adev->device.get_mic_mute = adev_get_mic_mute;
3682 adev->device.set_parameters = adev_set_parameters;
3683 adev->device.get_parameters = adev_get_parameters;
3684 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3685 adev->device.open_output_stream = adev_open_output_stream;
3686 adev->device.close_output_stream = adev_close_output_stream;
3687 adev->device.open_input_stream = adev_open_input_stream;
3688 adev->device.close_input_stream = adev_close_input_stream;
3689 adev->device.dump = adev_dump;
3690
3691 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003693 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003694 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003697 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003698 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003699 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003700 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003701 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003702 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003703 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303704
3705 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3706 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003708 adev->platform = platform_init(adev);
3709 if (!adev->platform) {
3710 free(adev->snd_dev_ref_cnt);
3711 free(adev);
3712 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3713 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003714 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003715 return -EINVAL;
3716 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003717
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3719
Eric Laurentc4aef752013-09-12 17:45:53 -07003720 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3721 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3722 if (adev->visualizer_lib == NULL) {
3723 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3724 } else {
3725 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3726 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003727 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003728 "visualizer_hal_start_output");
3729 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003730 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003731 "visualizer_hal_stop_output");
3732 }
3733 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003734 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003735 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003736
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003737 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3738 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3739 if (adev->offload_effects_lib == NULL) {
3740 ALOGE("%s: DLOPEN failed for %s", __func__,
3741 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3742 } else {
3743 ALOGV("%s: DLOPEN successful for %s", __func__,
3744 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3745 adev->offload_effects_start_output =
3746 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3747 "offload_effects_bundle_hal_start_output");
3748 adev->offload_effects_stop_output =
3749 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3750 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003751 adev->offload_effects_set_hpx_state =
3752 (int (*)(bool))dlsym(adev->offload_effects_lib,
3753 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003754 }
3755 }
3756
Mingming Yin514a8bc2014-07-29 15:22:21 -07003757 adev->bt_wb_speech_enabled = false;
3758
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003759 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 *device = &adev->device.common;
3761
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003762 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3763 &adev->streams_output_cfg_list);
3764
Kiran Kandi910e1862013-10-29 13:29:42 -07003765 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003766
3767 char value[PROPERTY_VALUE_MAX];
3768 int trial;
3769 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3770 trial = atoi(value);
3771 if (period_size_is_plausible_for_low_latency(trial)) {
3772 pcm_config_low_latency.period_size = trial;
3773 pcm_config_low_latency.start_threshold = trial / 4;
3774 pcm_config_low_latency.avail_min = trial / 4;
3775 configured_low_latency_capture_period_size = trial;
3776 }
3777 }
3778 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3779 trial = atoi(value);
3780 if (period_size_is_plausible_for_low_latency(trial)) {
3781 configured_low_latency_capture_period_size = trial;
3782 }
3783 }
3784
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003785 pthread_mutex_unlock(&adev_init_lock);
3786
Eric Laurent994a6932013-07-17 11:51:42 -07003787 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 return 0;
3789}
3790
3791static struct hw_module_methods_t hal_module_methods = {
3792 .open = adev_open,
3793};
3794
3795struct audio_module HAL_MODULE_INFO_SYM = {
3796 .common = {
3797 .tag = HARDWARE_MODULE_TAG,
3798 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3799 .hal_api_version = HARDWARE_HAL_API_VERSION,
3800 .id = AUDIO_HARDWARE_MODULE_ID,
3801 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003802 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 .methods = &hal_module_methods,
3804 },
3805};