blob: ad565de6aefe37442679dcc197aa0f785c73cd97 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, 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
Ashish Jain5106d362016-05-11 19:23:33 +053077/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
78#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080080#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070081#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
82
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070083#define PROXY_OPEN_RETRY_COUNT 100
84#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080085
Mingming Yin08c7e312015-03-16 18:10:58 -070086#ifdef USE_LL_AS_PRIMARY_OUTPUT
87#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
88#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
89#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080090#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070091#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
92#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080093
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070094static unsigned int configured_low_latency_capture_period_size =
95 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
96
Eric Laurentb23d5282013-05-14 15:27:20 -070097struct pcm_config pcm_config_deep_buffer = {
98 .channels = 2,
99 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
100 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
101 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104 .stop_threshold = INT_MAX,
105 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
106};
107
108struct pcm_config pcm_config_low_latency = {
109 .channels = 2,
110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
112 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_hdmi_multi = {
120 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
122 .period_size = HDMI_MULTI_PERIOD_SIZE,
123 .period_count = HDMI_MULTI_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = 0,
126 .stop_threshold = INT_MAX,
127 .avail_min = 0,
128};
129
130struct pcm_config pcm_config_audio_capture = {
131 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700132 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
133 .format = PCM_FORMAT_S16_LE,
134};
135
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700136#define AFE_PROXY_CHANNEL_COUNT 2
137#define AFE_PROXY_SAMPLING_RATE 48000
138
139#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
140#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
141
142struct pcm_config pcm_config_afe_proxy_playback = {
143 .channels = AFE_PROXY_CHANNEL_COUNT,
144 .rate = AFE_PROXY_SAMPLING_RATE,
145 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
146 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
147 .format = PCM_FORMAT_S16_LE,
148 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149 .stop_threshold = INT_MAX,
150 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
151};
152
153#define AFE_PROXY_RECORD_PERIOD_SIZE 768
154#define AFE_PROXY_RECORD_PERIOD_COUNT 4
155
156struct pcm_config pcm_config_afe_proxy_record = {
157 .channels = AFE_PROXY_CHANNEL_COUNT,
158 .rate = AFE_PROXY_SAMPLING_RATE,
159 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
160 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
163 .stop_threshold = INT_MAX,
164 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
165};
166
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800167const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700168 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
169 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700170 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
171 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700173 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700174 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
180 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
181 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700217 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,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700225};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226
227#define STRING_TO_ENUM(string) { #string, string }
228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229struct string_to_enum {
230 const char *name;
231 uint32_t value;
232};
233
234static const struct string_to_enum out_channels_name_to_enum_table[] = {
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
243};
244
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700245static const struct string_to_enum out_formats_name_to_enum_table[] = {
246 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
247 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800249 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
250 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
251};
252
253//list of all supported sample rates by HDMI specification.
254static const int out_hdmi_sample_rates[] = {
255 32000, 44100, 48000, 88200, 96000, 176400, 192000,
256};
257
258static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
259 STRING_TO_ENUM(32000),
260 STRING_TO_ENUM(44100),
261 STRING_TO_ENUM(48000),
262 STRING_TO_ENUM(88200),
263 STRING_TO_ENUM(96000),
264 STRING_TO_ENUM(176400),
265 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700266};
267
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700268static struct audio_device *adev = NULL;
269static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700270static unsigned int audio_device_ref_count;
271
vivek mehtaa76401a2015-04-24 14:12:15 -0700272__attribute__ ((visibility ("default")))
273bool audio_hw_send_gain_dep_calibration(int level) {
274 bool ret_val = false;
275 ALOGV("%s: called ... ", __func__);
276
277 pthread_mutex_lock(&adev_init_lock);
278
279 if (adev != NULL && adev->platform != NULL) {
280 pthread_mutex_lock(&adev->lock);
281 ret_val = platform_send_gain_dep_cal(adev->platform, level);
282 pthread_mutex_unlock(&adev->lock);
283 } else {
284 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
285 }
286
287 pthread_mutex_unlock(&adev_init_lock);
288
289 return ret_val;
290}
291
Ashish Jain5106d362016-05-11 19:23:33 +0530292static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
293{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800294 bool gapless_enabled = false;
295 const char *mixer_ctl_name = "Compress Gapless Playback";
296 struct mixer_ctl *ctl;
297
298 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530299 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
300
301 /*Disable gapless if its AV playback*/
302 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800303
304 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
305 if (!ctl) {
306 ALOGE("%s: Could not get ctl for mixer cmd - %s",
307 __func__, mixer_ctl_name);
308 return -EINVAL;
309 }
310
311 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
312 ALOGE("%s: Could not set gapless mode %d",
313 __func__, gapless_enabled);
314 return -EINVAL;
315 }
316 return 0;
317}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700318
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700319static bool is_supported_format(audio_format_t format)
320{
Eric Laurent86e17132013-09-12 17:49:30 -0700321 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530322 format == AUDIO_FORMAT_AAC_LC ||
323 format == AUDIO_FORMAT_AAC_HE_V1 ||
324 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530325 format == AUDIO_FORMAT_AAC_ADTS_LC ||
326 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
327 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530328 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
329 format == AUDIO_FORMAT_PCM_8_24_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700330 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800331 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530332 format == AUDIO_FORMAT_ALAC ||
333 format == AUDIO_FORMAT_APE ||
334 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800335 format == AUDIO_FORMAT_WMA ||
336 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800337 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700338
339 return false;
340}
341
342static int get_snd_codec_id(audio_format_t format)
343{
344 int id = 0;
345
Ashish Jainf9b78162014-08-25 20:36:25 +0530346 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700347 case AUDIO_FORMAT_MP3:
348 id = SND_AUDIOCODEC_MP3;
349 break;
350 case AUDIO_FORMAT_AAC:
351 id = SND_AUDIOCODEC_AAC;
352 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530353 case AUDIO_FORMAT_AAC_ADTS:
354 id = SND_AUDIOCODEC_AAC;
355 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700356 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800357 id = SND_AUDIOCODEC_PCM;
358 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700359 case AUDIO_FORMAT_FLAC:
360 id = SND_AUDIOCODEC_FLAC;
361 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530362 case AUDIO_FORMAT_ALAC:
363 id = SND_AUDIOCODEC_ALAC;
364 break;
365 case AUDIO_FORMAT_APE:
366 id = SND_AUDIOCODEC_APE;
367 break;
368 case AUDIO_FORMAT_VORBIS:
369 id = SND_AUDIOCODEC_VORBIS;
370 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800371 case AUDIO_FORMAT_WMA:
372 id = SND_AUDIOCODEC_WMA;
373 break;
374 case AUDIO_FORMAT_WMA_PRO:
375 id = SND_AUDIOCODEC_WMA_PRO;
376 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700377 default:
Mingming Yin90310102013-11-13 16:57:00 -0800378 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700379 }
380
381 return id;
382}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800383
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530384int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530385{
386 int snd_scard_state;
387
388 if (!adev)
389 return SND_CARD_STATE_OFFLINE;
390
391 pthread_mutex_lock(&adev->snd_card_status.lock);
392 snd_scard_state = adev->snd_card_status.state;
393 pthread_mutex_unlock(&adev->snd_card_status.lock);
394
395 return snd_scard_state;
396}
397
398static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
399{
400 if (!adev)
401 return -ENOSYS;
402
403 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700404 if (adev->snd_card_status.state != snd_scard_state) {
405 adev->snd_card_status.state = snd_scard_state;
406 platform_snd_card_update(adev->platform, snd_scard_state);
407 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530408 pthread_mutex_unlock(&adev->snd_card_status.lock);
409
410 return 0;
411}
412
Avinash Vaish71a8b972014-07-24 15:36:33 +0530413static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
414 struct audio_usecase *uc_info)
415{
416 struct listnode *node;
417 struct audio_usecase *usecase;
418
419 if (uc_info == NULL)
420 return -EINVAL;
421
422 /* Re-route all voice usecases on the shared backend other than the
423 specified usecase to new snd devices */
424 list_for_each(node, &adev->usecase_list) {
425 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800426 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530427 enable_audio_route(adev, usecase);
428 }
429 return 0;
430}
431
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700432int pcm_ioctl(struct pcm *pcm, int request, ...)
433{
434 va_list ap;
435 void * arg;
436 int pcm_fd = *(int*)pcm;
437
438 va_start(ap, request);
439 arg = va_arg(ap, void *);
440 va_end(ap);
441
442 return ioctl(pcm_fd, request, arg);
443}
444
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700445int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700446 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800447{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700448 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700449 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800450
451 if (usecase == NULL)
452 return -EINVAL;
453
454 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
455
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800456 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800458 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700459 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800460
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800461#ifdef DS1_DOLBY_DAP_ENABLED
462 audio_extn_dolby_set_dmid(adev);
463 audio_extn_dolby_set_endpoint(adev);
464#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700465 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700466 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530467 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700468 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530469 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800470 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700471 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700472 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700473 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800474 ALOGV("%s: exit", __func__);
475 return 0;
476}
477
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700478int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700479 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800480{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700481 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700482 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800483
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530484 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800485 return -EINVAL;
486
487 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488 if (usecase->type == PCM_CAPTURE)
489 snd_device = usecase->in_snd_device;
490 else
491 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800492 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700493 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700494 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700495 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700496 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530497 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800498 ALOGV("%s: exit", __func__);
499 return 0;
500}
501
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700502int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700503 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800504{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530505 int i, num_devices = 0;
506 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700507 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
508
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800509 if (snd_device < SND_DEVICE_MIN ||
510 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800511 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800512 return -EINVAL;
513 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700514
515 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700516
517 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
518 ALOGE("%s: Invalid sound device returned", __func__);
519 return -EINVAL;
520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700522 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700523 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700524 return 0;
525 }
526
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530527
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700528 if (audio_extn_spkr_prot_is_enabled())
529 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700530 /* start usb playback thread */
531 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
532 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
533 audio_extn_usb_start_playback(adev);
534
535 /* start usb capture thread */
536 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
537 audio_extn_usb_start_capture(adev);
538
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800539 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
540 audio_extn_spkr_prot_is_enabled()) {
541 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700542 adev->snd_dev_ref_cnt[snd_device]--;
543 return -EINVAL;
544 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200545 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800546 if (audio_extn_spkr_prot_start_processing(snd_device)) {
547 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200548 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800549 return -EINVAL;
550 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530551 } else if (platform_can_split_snd_device(adev->platform, snd_device,
552 &num_devices, new_snd_devices)) {
553 for (i = 0; i < num_devices; i++) {
554 enable_snd_device(adev, new_snd_devices[i]);
555 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800556 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700557 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700558 /* due to the possibility of calibration overwrite between listen
559 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700560 audio_extn_sound_trigger_update_device_status(snd_device,
561 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530562 audio_extn_listen_update_device_status(snd_device,
563 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700564 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700565 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566 audio_extn_sound_trigger_update_device_status(snd_device,
567 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530568 audio_extn_listen_update_device_status(snd_device,
569 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700570 return -EINVAL;
571 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300572 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700573 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530574
575 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
576 !adev->native_playback_enabled &&
577 audio_is_true_native_stream_active(adev)) {
578 ALOGD("%s: %d: napb: enabling native mode in hardware",
579 __func__, __LINE__);
580 audio_route_apply_and_update_path(adev->audio_route,
581 "true-native-mode");
582 adev->native_playback_enabled = true;
583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800584 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800585 return 0;
586}
587
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700588int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700589 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800590{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530591 int i, num_devices = 0;
592 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700593 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
594
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800595 if (snd_device < SND_DEVICE_MIN ||
596 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800597 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800598 return -EINVAL;
599 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
601 ALOGE("%s: device ref cnt is already 0", __func__);
602 return -EINVAL;
603 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700606
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700607 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
608 ALOGE("%s: Invalid sound device returned", __func__);
609 return -EINVAL;
610 }
611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700613 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800614 /* exit usb play back thread */
615 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
616 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
617 audio_extn_usb_stop_playback();
618
619 /* exit usb capture thread */
620 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700621 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800622
623 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
624 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700625 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530626 } else if (platform_can_split_snd_device(adev->platform, snd_device,
627 &num_devices, new_snd_devices)) {
628 for (i = 0; i < num_devices; i++) {
629 disable_snd_device(adev, new_snd_devices[i]);
630 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300631 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700632 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300633 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700634
Ashish Jain81eb2a82015-05-13 10:52:34 +0530635 if (snd_device == SND_DEVICE_OUT_HDMI)
636 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530637 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
638 adev->native_playback_enabled) {
639 ALOGD("%s: %d: napb: disabling native mode in hardware",
640 __func__, __LINE__);
641 audio_route_reset_and_update_path(adev->audio_route,
642 "true-native-mode");
643 adev->native_playback_enabled = false;
644 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530645
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200646 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700647 audio_extn_sound_trigger_update_device_status(snd_device,
648 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530649 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800650 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653 return 0;
654}
655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530657 struct audio_usecase *uc_info,
658 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659{
660 struct listnode *node;
661 struct audio_usecase *usecase;
662 bool switch_device[AUDIO_USECASE_MAX];
663 int i, num_uc_to_switch = 0;
664
665 /*
666 * This function is to make sure that all the usecases that are active on
667 * the hardware codec backend are always routed to any one device that is
668 * handled by the hardware codec.
669 * For example, if low-latency and deep-buffer usecases are currently active
670 * on speaker and out_set_parameters(headset) is received on low-latency
671 * output, then we have to make sure deep-buffer is also switched to headset,
672 * because of the limitation that both the devices cannot be enabled
673 * at the same time as they share the same backend.
674 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700675 /*
676 * This call is to check if we need to force routing for a particular stream
677 * If there is a backend configuration change for the device when a
678 * new stream starts, then ADM needs to be closed and re-opened with the new
679 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700681 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800682 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
683 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530684
685 ALOGD("%s:becf: force routing %d", __func__, force_routing);
686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700687 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800688 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800689 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700690 for (i = 0; i < AUDIO_USECASE_MAX; i++)
691 switch_device[i] = false;
692
693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800695
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530696 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
697 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530698 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530699 platform_get_snd_device_name(usecase->out_snd_device),
700 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800701 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530702 usecase != uc_info &&
703 (usecase->out_snd_device != snd_device || force_routing) &&
704 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
705 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
706 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
707 __func__, use_case_table[usecase->id],
708 platform_get_snd_device_name(usecase->out_snd_device));
709 disable_audio_route(adev, usecase);
710 switch_device[usecase->id] = true;
711 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 }
713 }
714
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530715 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
716 num_uc_to_switch);
717
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700718 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700719 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530721 /* Make sure the previous devices to be disabled first and then enable the
722 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 list_for_each(node, &adev->usecase_list) {
724 usecase = node_to_item(node, struct audio_usecase, list);
725 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727 }
728 }
729
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700733 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700734 }
735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 /* Re-route all the usecases on the shared backend other than the
738 specified usecase to new snd devices */
739 list_for_each(node, &adev->usecase_list) {
740 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530741 /* Update the out_snd_device only before enabling the audio route */
742 if (switch_device[usecase->id]) {
743 usecase->out_snd_device = snd_device;
744 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530745 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530746 use_case_table[usecase->id],
747 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530748 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530749 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 }
751 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752 }
753}
754
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530755static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 struct audio_usecase *uc_info,
757 snd_device_t snd_device)
758{
759 struct listnode *node;
760 struct audio_usecase *usecase;
761 bool switch_device[AUDIO_USECASE_MAX];
762 int i, num_uc_to_switch = 0;
763
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530764 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
765 snd_device);
766 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 /*
768 * This function is to make sure that all the active capture usecases
769 * are always routed to the same input sound device.
770 * For example, if audio-record and voice-call usecases are currently
771 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
772 * is received for voice call then we have to make sure that audio-record
773 * usecase is also switched to earpiece i.e. voice-dmic-ef,
774 * because of the limitation that two devices cannot be enabled
775 * at the same time if they share the same backend.
776 */
777 for (i = 0; i < AUDIO_USECASE_MAX; i++)
778 switch_device[i] = false;
779
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800782 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700783 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530784 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700785 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530786 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
787 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700788 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
790 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700791 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700792 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700793 switch_device[usecase->id] = true;
794 num_uc_to_switch++;
795 }
796 }
797
798 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700799 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700800
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530801 /* Make sure the previous devices to be disabled first and then enable the
802 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700803 list_for_each(node, &adev->usecase_list) {
804 usecase = node_to_item(node, struct audio_usecase, list);
805 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700806 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800807 }
808 }
809
810 list_for_each(node, &adev->usecase_list) {
811 usecase = node_to_item(node, struct audio_usecase, list);
812 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700813 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700814 }
815 }
816
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700817 /* Re-route all the usecases on the shared backend other than the
818 specified usecase to new snd devices */
819 list_for_each(node, &adev->usecase_list) {
820 usecase = node_to_item(node, struct audio_usecase, list);
821 /* Update the in_snd_device only before enabling the audio route */
822 if (switch_device[usecase->id] ) {
823 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800824 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530825 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700826 }
827 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700828 }
829}
830
Mingming Yin3a941d42016-02-17 18:08:05 -0800831static void reset_hdmi_sink_caps(struct stream_out *out) {
832 int i = 0;
833
834 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
835 out->supported_channel_masks[i] = 0;
836 }
837 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
838 out->supported_formats[i] = 0;
839 }
840 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
841 out->supported_sample_rates[i] = 0;
842 }
843}
844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800846static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847{
Mingming Yin3a941d42016-02-17 18:08:05 -0800848 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700849 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850
Mingming Yin3a941d42016-02-17 18:08:05 -0800851 reset_hdmi_sink_caps(out);
852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800855 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800857 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
858 case 6:
859 ALOGV("%s: HDMI supports 5.1 channels", __func__);
860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
862 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
863 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
864 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
865 case 2:
866 ALOGV("%s: HDMI supports 2 channels", __func__);
867 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800868 break;
869 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800870 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700871 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872 break;
873 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800874
875 // check channel format caps
876 i = 0;
877 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
878 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
879 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
880 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
881 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
882 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
883 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
884 }
885
886 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
887 ALOGV(":%s HDMI supports DTS format", __func__);
888 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
889 }
890
891 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
892 ALOGV(":%s HDMI supports DTS HD format", __func__);
893 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
894 }
895
896
897 // check sample rate caps
898 i = 0;
899 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
900 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
901 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
902 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
903 }
904 }
905
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700906 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800907}
908
Alexy Josephb1379942016-01-29 15:49:38 -0800909audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800910 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700911{
912 struct audio_usecase *usecase;
913 struct listnode *node;
914
915 list_for_each(node, &adev->usecase_list) {
916 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800917 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700918 ALOGV("%s: usecase id %d", __func__, usecase->id);
919 return usecase->id;
920 }
921 }
922 return USECASE_INVALID;
923}
924
Alexy Josephb1379942016-01-29 15:49:38 -0800925struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700926 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927{
928 struct audio_usecase *usecase;
929 struct listnode *node;
930
931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
933 if (usecase->id == uc_id)
934 return usecase;
935 }
936 return NULL;
937}
938
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530939/*
940 * is a true native playback active
941 */
942bool audio_is_true_native_stream_active(struct audio_device *adev)
943{
944 bool active = false;
945 int i = 0;
946 struct listnode *node;
947
948 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
949 ALOGV("%s:napb: not in true mode or non hdphones device",
950 __func__);
951 active = false;
952 goto exit;
953 }
954
955 list_for_each(node, &adev->usecase_list) {
956 struct audio_usecase *uc;
957 uc = node_to_item(node, struct audio_usecase, list);
958 struct stream_out *curr_out =
959 (struct stream_out*) uc->stream.out;
960
961 if (curr_out && PCM_PLAYBACK == uc->type) {
962 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
963 "(%d) device %s", __func__, i++, use_case_table[uc->id],
964 uc->id, curr_out->sample_rate,
965 curr_out->bit_width,
966 platform_get_snd_device_name(uc->out_snd_device));
967
968 if (is_offload_usecase(uc->id) &&
969 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
970 active = true;
971 ALOGD("%s:napb:native stream detected", __func__);
972 }
973 }
974 }
975exit:
976 return active;
977}
978
979
980static bool force_device_switch(struct audio_usecase *usecase)
981{
982 bool ret = false;
983 bool is_it_true_mode = false;
984
985 if (is_offload_usecase(usecase->id) &&
986 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800987 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
988 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
989 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530990 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
991 if ((is_it_true_mode && !adev->native_playback_enabled) ||
992 (!is_it_true_mode && adev->native_playback_enabled)){
993 ret = true;
994 ALOGD("napb: time to toggle native mode");
995 }
996 }
997
998 return ret;
999}
1000
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001001int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001003 snd_device_t out_snd_device = SND_DEVICE_NONE;
1004 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001005 struct audio_usecase *usecase = NULL;
1006 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001007 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001008 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001009 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001011
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301012 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1013
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001014 usecase = get_usecase_from_list(adev, uc_id);
1015 if (usecase == NULL) {
1016 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1017 return -EINVAL;
1018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001020 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001021 (usecase->type == VOIP_CALL) ||
1022 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001023 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001024 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001025 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 usecase->devices = usecase->stream.out->devices;
1027 } else {
1028 /*
1029 * If the voice call is active, use the sound devices of voice call usecase
1030 * so that it would not result any device switch. All the usecases will
1031 * be switched to new device when select_devices() is called for voice call
1032 * usecase. This is to avoid switching devices for voice call when
1033 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001034 * choose voice call device only if the use case device is
1035 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001037 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001038 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001039 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001040 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1041 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1042 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 in_snd_device = vc_usecase->in_snd_device;
1044 out_snd_device = vc_usecase->out_snd_device;
1045 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001046 } else if (voice_extn_compress_voip_is_active(adev)) {
1047 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001048 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301049 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001050 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001051 in_snd_device = voip_usecase->in_snd_device;
1052 out_snd_device = voip_usecase->out_snd_device;
1053 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001054 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001055 hfp_ucid = audio_extn_hfp_get_usecase();
1056 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001057 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001058 in_snd_device = hfp_usecase->in_snd_device;
1059 out_snd_device = hfp_usecase->out_snd_device;
1060 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 }
1062 if (usecase->type == PCM_PLAYBACK) {
1063 usecase->devices = usecase->stream.out->devices;
1064 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001065 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001066 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001067 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001068 if (usecase->stream.out == adev->primary_output &&
1069 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001070 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 select_devices(adev, adev->active_input->usecase);
1072 }
1073 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 } else if (usecase->type == PCM_CAPTURE) {
1075 usecase->devices = usecase->stream.in->device;
1076 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001077 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001078 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001079 if (adev->active_input &&
1080 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301081 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1082 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1083 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001084 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001085 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001086 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1087 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001088 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001089 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 }
1092 }
1093
1094 if (out_snd_device == usecase->out_snd_device &&
1095 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301096
1097 if (!force_device_switch(usecase))
1098 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 }
1100
sangwoobc677242013-08-08 16:53:43 +09001101 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001102 out_snd_device, platform_get_snd_device_name(out_snd_device),
1103 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 /*
1106 * Limitation: While in call, to do a device switch we need to disable
1107 * and enable both RX and TX devices though one of them is same as current
1108 * device.
1109 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001110 if ((usecase->type == VOICE_CALL) &&
1111 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1112 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001113 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001114 }
1115
1116 if (((usecase->type == VOICE_CALL) ||
1117 (usecase->type == VOIP_CALL)) &&
1118 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1119 /* Disable sidetone only if voice/voip call already exists */
1120 if (voice_is_call_state_active(adev) ||
1121 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001122 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001123 }
1124
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 /* Disable current sound devices */
1126 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001127 disable_audio_route(adev, usecase);
1128 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 }
1130
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001132 disable_audio_route(adev, usecase);
1133 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 }
1135
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001136 /* Applicable only on the targets that has external modem.
1137 * New device information should be sent to modem before enabling
1138 * the devices to reduce in-call device switch time.
1139 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001140 if ((usecase->type == VOICE_CALL) &&
1141 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1142 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001143 status = platform_switch_voice_call_enable_device_config(adev->platform,
1144 out_snd_device,
1145 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001146 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001147
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 /* Enable new sound devices */
1149 if (out_snd_device != SND_DEVICE_NONE) {
1150 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1151 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001152 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153 }
1154
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301156 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001157 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159
Avinash Vaish71a8b972014-07-24 15:36:33 +05301160 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001161 status = platform_switch_voice_call_device_post(adev->platform,
1162 out_snd_device,
1163 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301164 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001165 /* Enable sidetone only if voice/voip call already exists */
1166 if (voice_is_call_state_active(adev) ||
1167 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001168 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301169 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001170
sangwoo170731f2013-06-08 15:36:36 +09001171 usecase->in_snd_device = in_snd_device;
1172 usecase->out_snd_device = out_snd_device;
1173
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301174 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001175 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301176 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001177 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301178 usecase->stream.out->flags,
1179 usecase->stream.out->format,
1180 usecase->stream.out->sample_rate,
1181 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301182 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301183 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001184 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301185 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001186
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001187 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001188
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001189 /* Applicable only on the targets that has external modem.
1190 * Enable device command should be sent to modem only after
1191 * enabling voice call mixer controls
1192 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001193 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001194 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1195 out_snd_device,
1196 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301197 ALOGD("%s: done",__func__);
1198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 return status;
1200}
1201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202static int stop_input_stream(struct stream_in *in)
1203{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301204 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205 struct audio_usecase *uc_info;
1206 struct audio_device *adev = in->dev;
1207
Eric Laurentc8400632013-02-14 19:04:54 -08001208 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209
Eric Laurent994a6932013-07-17 11:51:42 -07001210 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 uc_info = get_usecase_from_list(adev, in->usecase);
1213 if (uc_info == NULL) {
1214 ALOGE("%s: Could not find the usecase (%d) in the list",
1215 __func__, in->usecase);
1216 return -EINVAL;
1217 }
1218
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001219 /* Close in-call recording streams */
1220 voice_check_and_stop_incall_rec_usecase(adev, in);
1221
Eric Laurent150dbfe2013-02-27 14:31:02 -08001222 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001223 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224
1225 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001226 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001228 list_remove(&uc_info->list);
1229 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230
Eric Laurent994a6932013-07-17 11:51:42 -07001231 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 return ret;
1233}
1234
1235int start_input_stream(struct stream_in *in)
1236{
1237 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001238 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239 struct audio_usecase *uc_info;
1240 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301241 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242
Mingming Yin2664a5b2015-09-03 10:53:11 -07001243 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1244 if (get_usecase_from_list(adev, usecase) == NULL)
1245 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301246 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1247 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001248
Naresh Tanniru80659832014-06-04 18:17:56 +05301249
1250 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301251 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301252 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301253 goto error_config;
1254 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301255
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001256 /* Check if source matches incall recording usecase criteria */
1257 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1258 if (ret)
1259 goto error_config;
1260 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001261 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1262
1263 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1264 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1265 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1266 goto error_config;
1267 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001268
Eric Laurentb23d5282013-05-14 15:27:20 -07001269 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 if (in->pcm_device_id < 0) {
1271 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1272 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001273 ret = -EINVAL;
1274 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276
1277 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001279
1280 if (!uc_info) {
1281 ret = -ENOMEM;
1282 goto error_config;
1283 }
1284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 uc_info->id = in->usecase;
1286 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 uc_info->devices = in->device;
1289 uc_info->in_snd_device = SND_DEVICE_NONE;
1290 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001292 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301293 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1294 adev->perf_lock_opts,
1295 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301298 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1299 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001300
1301 unsigned int flags = PCM_IN;
1302 unsigned int pcm_open_retry_count = 0;
1303
1304 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1305 flags |= PCM_MMAP | PCM_NOIRQ;
1306 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1307 }
1308
1309 while (1) {
1310 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1311 flags, &in->config);
1312 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1313 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1314 if (in->pcm != NULL) {
1315 pcm_close(in->pcm);
1316 in->pcm = NULL;
1317 }
1318 if (pcm_open_retry_count-- == 0) {
1319 ret = -EIO;
1320 goto error_open;
1321 }
1322 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1323 continue;
1324 }
1325 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001327
1328 ALOGV("%s: pcm_prepare", __func__);
1329 ret = pcm_prepare(in->pcm);
1330 if (ret < 0) {
1331 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1332 pcm_close(in->pcm);
1333 in->pcm = NULL;
1334 goto error_open;
1335 }
1336
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301337 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001338 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001339
Eric Laurentc8400632013-02-14 19:04:54 -08001340 return ret;
1341
1342error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301343 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001345error_config:
1346 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301347 /*
1348 * sleep 50ms to allow sufficient time for kernel
1349 * drivers to recover incases like SSR.
1350 */
1351 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001353
1354 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001355}
1356
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001357void lock_input_stream(struct stream_in *in)
1358{
1359 pthread_mutex_lock(&in->pre_lock);
1360 pthread_mutex_lock(&in->lock);
1361 pthread_mutex_unlock(&in->pre_lock);
1362}
1363
1364void lock_output_stream(struct stream_out *out)
1365{
1366 pthread_mutex_lock(&out->pre_lock);
1367 pthread_mutex_lock(&out->lock);
1368 pthread_mutex_unlock(&out->pre_lock);
1369}
1370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001371/* must be called with out->lock locked */
1372static int send_offload_cmd_l(struct stream_out* out, int command)
1373{
1374 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1375
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001376 if (!cmd) {
1377 ALOGE("failed to allocate mem for command 0x%x", command);
1378 return -ENOMEM;
1379 }
1380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 ALOGVV("%s %d", __func__, command);
1382
1383 cmd->cmd = command;
1384 list_add_tail(&out->offload_cmd_list, &cmd->node);
1385 pthread_cond_signal(&out->offload_cond);
1386 return 0;
1387}
1388
1389/* must be called iwth out->lock locked */
1390static void stop_compressed_output_l(struct stream_out *out)
1391{
1392 out->offload_state = OFFLOAD_STATE_IDLE;
1393 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001394 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001395 if (out->compr != NULL) {
1396 compress_stop(out->compr);
1397 while (out->offload_thread_blocked) {
1398 pthread_cond_wait(&out->cond, &out->lock);
1399 }
1400 }
1401}
1402
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001403bool is_offload_usecase(audio_usecase_t uc_id)
1404{
1405 unsigned int i;
1406 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1407 if (uc_id == offload_usecases[i])
1408 return true;
1409 }
1410 return false;
1411}
1412
vivek mehta446c3962015-09-14 10:57:35 -07001413static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001414{
vivek mehta446c3962015-09-14 10:57:35 -07001415 audio_usecase_t ret_uc = USECASE_INVALID;
1416 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001417 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001418 if (!adev->multi_offload_enable) {
1419 if (is_direct_pcm)
1420 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1421 else
1422 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423
vivek mehta446c3962015-09-14 10:57:35 -07001424 pthread_mutex_lock(&adev->lock);
1425 if (get_usecase_from_list(adev, ret_uc) != NULL)
1426 ret_uc = USECASE_INVALID;
1427 pthread_mutex_unlock(&adev->lock);
1428
1429 return ret_uc;
1430 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001431
1432 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001433 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1434 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1435 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1436 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001437 break;
1438 }
1439 }
vivek mehta446c3962015-09-14 10:57:35 -07001440
1441 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1442 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001443}
1444
1445static void free_offload_usecase(struct audio_device *adev,
1446 audio_usecase_t uc_id)
1447{
vivek mehta446c3962015-09-14 10:57:35 -07001448 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001449 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001450
1451 if (!adev->multi_offload_enable)
1452 return;
1453
1454 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1455 if (offload_usecases[offload_uc_index] == uc_id) {
1456 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001457 break;
1458 }
1459 }
1460 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1461}
1462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001463static void *offload_thread_loop(void *context)
1464{
1465 struct stream_out *out = (struct stream_out *) context;
1466 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001467 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001469 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1470 set_sched_policy(0, SP_FOREGROUND);
1471 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1472
1473 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001474 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001475 for (;;) {
1476 struct offload_cmd *cmd = NULL;
1477 stream_callback_event_t event;
1478 bool send_callback = false;
1479
1480 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1481 __func__, list_empty(&out->offload_cmd_list),
1482 out->offload_state);
1483 if (list_empty(&out->offload_cmd_list)) {
1484 ALOGV("%s SLEEPING", __func__);
1485 pthread_cond_wait(&out->offload_cond, &out->lock);
1486 ALOGV("%s RUNNING", __func__);
1487 continue;
1488 }
1489
1490 item = list_head(&out->offload_cmd_list);
1491 cmd = node_to_item(item, struct offload_cmd, node);
1492 list_remove(item);
1493
1494 ALOGVV("%s STATE %d CMD %d out->compr %p",
1495 __func__, out->offload_state, cmd->cmd, out->compr);
1496
1497 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1498 free(cmd);
1499 break;
1500 }
1501
1502 if (out->compr == NULL) {
1503 ALOGE("%s: Compress handle is NULL", __func__);
1504 pthread_cond_signal(&out->cond);
1505 continue;
1506 }
1507 out->offload_thread_blocked = true;
1508 pthread_mutex_unlock(&out->lock);
1509 send_callback = false;
1510 switch(cmd->cmd) {
1511 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001512 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001513 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001514 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001515 send_callback = true;
1516 event = STREAM_CBK_EVENT_WRITE_READY;
1517 break;
1518 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001519 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301520 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001521 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301522 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001523 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301524 if (ret < 0)
1525 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301526 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301527 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001528 compress_drain(out->compr);
1529 else
1530 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301531 if (ret != -ENETRESET) {
1532 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301533 pthread_mutex_lock(&out->lock);
1534 out->send_new_metadata = 1;
1535 out->send_next_track_params = true;
1536 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301537 event = STREAM_CBK_EVENT_DRAIN_READY;
1538 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1539 } else
1540 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001541 break;
1542 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001543 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001545 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001546 send_callback = true;
1547 event = STREAM_CBK_EVENT_DRAIN_READY;
1548 break;
1549 default:
1550 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1551 break;
1552 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001553 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001554 out->offload_thread_blocked = false;
1555 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001556 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001557 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001559 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001560 free(cmd);
1561 }
1562
1563 pthread_cond_signal(&out->cond);
1564 while (!list_empty(&out->offload_cmd_list)) {
1565 item = list_head(&out->offload_cmd_list);
1566 list_remove(item);
1567 free(node_to_item(item, struct offload_cmd, node));
1568 }
1569 pthread_mutex_unlock(&out->lock);
1570
1571 return NULL;
1572}
1573
1574static int create_offload_callback_thread(struct stream_out *out)
1575{
1576 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1577 list_init(&out->offload_cmd_list);
1578 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1579 offload_thread_loop, out);
1580 return 0;
1581}
1582
1583static int destroy_offload_callback_thread(struct stream_out *out)
1584{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001585 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 stop_compressed_output_l(out);
1587 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1588
1589 pthread_mutex_unlock(&out->lock);
1590 pthread_join(out->offload_thread, (void **) NULL);
1591 pthread_cond_destroy(&out->offload_cond);
1592
1593 return 0;
1594}
1595
Mingming Yin21854652016-04-13 11:54:02 -07001596static bool allow_hdmi_channel_config(struct audio_device *adev,
1597 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001598{
1599 struct listnode *node;
1600 struct audio_usecase *usecase;
1601 bool ret = true;
1602
Mingming Yin21854652016-04-13 11:54:02 -07001603 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1604 ret = false;
1605 goto exit;
1606 }
1607
1608 if (audio_extn_passthru_is_active()) {
1609 ALOGI("%s: Compress audio passthrough is active,"
1610 "no HDMI config change allowed", __func__);
1611 ret = false;
1612 goto exit;
1613 }
1614
Eric Laurent07eeafd2013-10-06 12:52:49 -07001615 list_for_each(node, &adev->usecase_list) {
1616 usecase = node_to_item(node, struct audio_usecase, list);
1617 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1618 /*
1619 * If voice call is already existing, do not proceed further to avoid
1620 * disabling/enabling both RX and TX devices, CSD calls, etc.
1621 * Once the voice call done, the HDMI channels can be configured to
1622 * max channels of remaining use cases.
1623 */
1624 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001625 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001626 __func__);
1627 ret = false;
1628 break;
1629 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001630 if (!enable_passthru) {
1631 ALOGV("%s: multi channel playback is active, "
1632 "no change in HDMI channels", __func__);
1633 ret = false;
1634 break;
1635 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001636 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001637 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001638 if (!enable_passthru) {
1639 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1640 ", no change in HDMI channels", __func__,
1641 usecase->stream.out->channel_mask);
1642 ret = false;
1643 break;
1644 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001645 }
1646 }
1647 }
Mingming Yin21854652016-04-13 11:54:02 -07001648 ALOGV("allow hdmi config %d", ret);
1649exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001650 return ret;
1651}
1652
Mingming Yin21854652016-04-13 11:54:02 -07001653static int check_and_set_hdmi_config(struct audio_device *adev,
1654 uint32_t channels,
1655 uint32_t sample_rate,
1656 audio_format_t format,
1657 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001658{
1659 struct listnode *node;
1660 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001661 int32_t factor = 1;
1662 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001663
Mingming Yin21854652016-04-13 11:54:02 -07001664 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1665 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001666
Mingming Yin21854652016-04-13 11:54:02 -07001667 if (channels != adev->cur_hdmi_channels) {
1668 ALOGV("channel does not match current hdmi channels");
1669 config = true;
1670 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001671
Mingming Yin21854652016-04-13 11:54:02 -07001672 if (sample_rate != adev->cur_hdmi_sample_rate) {
1673 ALOGV("sample rate does not match current hdmi sample rate");
1674 config = true;
1675 }
1676
1677 if (format != adev->cur_hdmi_format) {
1678 ALOGV("format does not match current hdmi format");
1679 config = true;
1680 }
1681
1682 /* TBD - add check for bit width */
1683 if (!config) {
1684 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001685 return 0;
1686 }
1687
Mingming Yin21854652016-04-13 11:54:02 -07001688 if (enable_passthru &&
1689 (format == AUDIO_FORMAT_E_AC3)) {
1690 ALOGV("factor 4 for E_AC3 passthru");
1691 factor = 4;
1692 }
1693
1694 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1695 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001696 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001697 adev->cur_hdmi_format = format;
1698 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001699
1700 /*
1701 * Deroute all the playback streams routed to HDMI so that
1702 * the back end is deactivated. Note that backend will not
1703 * be deactivated if any one stream is connected to it.
1704 */
1705 list_for_each(node, &adev->usecase_list) {
1706 usecase = node_to_item(node, struct audio_usecase, list);
1707 if (usecase->type == PCM_PLAYBACK &&
1708 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001709 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001710 }
1711 }
1712
Mingming Yin21854652016-04-13 11:54:02 -07001713 bool was_active = audio_extn_keep_alive_is_active();
1714 if (was_active)
1715 audio_extn_keep_alive_stop();
1716
Eric Laurent07eeafd2013-10-06 12:52:49 -07001717 /*
1718 * Enable all the streams disabled above. Now the HDMI backend
1719 * will be activated with new channel configuration
1720 */
1721 list_for_each(node, &adev->usecase_list) {
1722 usecase = node_to_item(node, struct audio_usecase, list);
1723 if (usecase->type == PCM_PLAYBACK &&
1724 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001725 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 }
1727 }
1728
Mingming Yin21854652016-04-13 11:54:02 -07001729 if (was_active)
1730 audio_extn_keep_alive_start();
1731
Eric Laurent07eeafd2013-10-06 12:52:49 -07001732 return 0;
1733}
1734
Mingming Yin21854652016-04-13 11:54:02 -07001735/* called with out lock taken */
1736static int check_and_set_hdmi_backend(struct stream_out *out)
1737{
1738 struct audio_device *adev = out->dev;
1739 int ret;
1740 bool enable_passthru = false;
1741
1742 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1743 return -1;
1744
1745 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1746
1747 if (is_offload_usecase(out->usecase) &&
1748 audio_extn_dolby_is_passthrough_stream(out)) {
1749 enable_passthru = true;
1750 }
1751
1752 /* Check if change in HDMI channel config is allowed */
1753 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1754 return -EPERM;
1755 }
1756
1757 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1758 uint32_t channels;
1759 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1760
1761 if (enable_passthru) {
1762 audio_extn_passthru_on_start(out);
1763 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1764 }
1765
1766 /* For pass through case, the backend should be configured as stereo */
1767 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1768 out->compr_config.codec->ch_in;
1769
1770 ret = check_and_set_hdmi_config(adev, channels,
1771 out->sample_rate, out->format,
1772 enable_passthru);
1773 } else
1774 ret = check_and_set_hdmi_config(adev, out->config.channels,
1775 out->config.rate,
1776 out->format,
1777 false);
1778 return ret;
1779}
1780
1781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782static int stop_output_stream(struct stream_out *out)
1783{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301784 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 struct audio_usecase *uc_info;
1786 struct audio_device *adev = out->dev;
1787
Eric Laurent994a6932013-07-17 11:51:42 -07001788 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 uc_info = get_usecase_from_list(adev, out->usecase);
1791 if (uc_info == NULL) {
1792 ALOGE("%s: Could not find the usecase (%d) in the list",
1793 __func__, out->usecase);
1794 return -EINVAL;
1795 }
1796
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001797 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001798 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001799 if (adev->visualizer_stop_output != NULL)
1800 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001801
1802 audio_extn_dts_remove_state_notifier_node(out->usecase);
1803
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001804 if (adev->offload_effects_stop_output != NULL)
1805 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1806 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001807
Eric Laurent150dbfe2013-02-27 14:31:02 -08001808 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001809 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810
1811 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001812 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001814 list_remove(&uc_info->list);
1815 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001817 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001818 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001819 ALOGV("Disable passthrough , reset mixer to pcm");
1820 /* NO_PASSTHROUGH */
1821 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001822
1823 /* Must be called after removing the usecase from list */
1824 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1825 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1826 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1827 DEFAULT_HDMI_OUT_FORMAT,
1828 false);
1829 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001830 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1831 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001832
Eric Laurent994a6932013-07-17 11:51:42 -07001833 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 return ret;
1835}
1836
1837int start_output_stream(struct stream_out *out)
1838{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 struct audio_usecase *uc_info;
1841 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301842 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001844 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1845 ret = -EINVAL;
1846 goto error_config;
1847 }
1848
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301849 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1850 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1851 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301852
Naresh Tanniru80659832014-06-04 18:17:56 +05301853 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301854 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301855 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301856 goto error_config;
1857 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301858
Eric Laurentb23d5282013-05-14 15:27:20 -07001859 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 if (out->pcm_device_id < 0) {
1861 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1862 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001863 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001864 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 }
1866
1867 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001868
1869 if (!uc_info) {
1870 ret = -ENOMEM;
1871 goto error_config;
1872 }
1873
Mingming Yin21854652016-04-13 11:54:02 -07001874 /* This must be called before adding this usecase to the list */
1875 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1876 /* This call can fail if compress pass thru is already active */
1877 check_and_set_hdmi_backend(out);
1878 }
1879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 uc_info->id = out->usecase;
1881 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001882 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 uc_info->devices = out->devices;
1884 uc_info->in_snd_device = SND_DEVICE_NONE;
1885 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001886 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301888 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1889 adev->perf_lock_opts,
1890 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 select_devices(adev, out->usecase);
1892
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001893 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1894 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001895 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001896 unsigned int flags = PCM_OUT;
1897 unsigned int pcm_open_retry_count = 0;
1898 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1899 flags |= PCM_MMAP | PCM_NOIRQ;
1900 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1901 } else
1902 flags |= PCM_MONOTONIC;
1903
1904 while (1) {
1905 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1906 flags, &out->config);
1907 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1908 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1909 if (out->pcm != NULL) {
1910 pcm_close(out->pcm);
1911 out->pcm = NULL;
1912 }
1913 if (pcm_open_retry_count-- == 0) {
1914 ret = -EIO;
1915 goto error_open;
1916 }
1917 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1918 continue;
1919 }
1920 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001921 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001922
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001923 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1924 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001925
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001926 ALOGV("%s: pcm_prepare", __func__);
1927 if (pcm_is_ready(out->pcm)) {
1928 ret = pcm_prepare(out->pcm);
1929 if (ret < 0) {
1930 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1931 pcm_close(out->pcm);
1932 out->pcm = NULL;
1933 goto error_open;
1934 }
1935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001937 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1938 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001940 out->compr = compress_open(adev->snd_card,
1941 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 COMPRESS_IN, &out->compr_config);
1943 if (out->compr && !is_compress_ready(out->compr)) {
1944 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1945 compress_close(out->compr);
1946 out->compr = NULL;
1947 ret = -EIO;
1948 goto error_open;
1949 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301950 /* compress_open sends params of the track, so reset the flag here */
1951 out->is_compr_metadata_avail = false;
1952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001953 if (out->offload_callback)
1954 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001955
Fred Oh3f43e742015-03-04 18:42:34 -08001956 /* Since small bufs uses blocking writes, a write will be blocked
1957 for the default max poll time (20s) in the event of an SSR.
1958 Reduce the poll time to observe and deal with SSR faster.
1959 */
Ashish Jain5106d362016-05-11 19:23:33 +05301960 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001961 compress_set_max_poll_wait(out->compr, 1000);
1962 }
1963
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001964 audio_extn_dts_create_state_notifier_node(out->usecase);
1965 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1966 popcount(out->channel_mask),
1967 out->playback_started);
1968
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001969#ifdef DS1_DOLBY_DDP_ENABLED
1970 if (audio_extn_is_dolby_format(out->format))
1971 audio_extn_dolby_send_ddp_endp_params(adev);
1972#endif
Mingming Yin21854652016-04-13 11:54:02 -07001973 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001974 if (adev->visualizer_start_output != NULL)
1975 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1976 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301977 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001978 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301981 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001982 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301986 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001988error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301989 /*
1990 * sleep 50ms to allow sufficient time for kernel
1991 * drivers to recover incases like SSR.
1992 */
1993 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001994 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995}
1996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997static int check_input_parameters(uint32_t sample_rate,
1998 audio_format_t format,
1999 int channel_count)
2000{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002001 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302003 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2004 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2005 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002006 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302007 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002008
2009 switch (channel_count) {
2010 case 1:
2011 case 2:
2012 case 6:
2013 break;
2014 default:
2015 ret = -EINVAL;
2016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017
2018 switch (sample_rate) {
2019 case 8000:
2020 case 11025:
2021 case 12000:
2022 case 16000:
2023 case 22050:
2024 case 24000:
2025 case 32000:
2026 case 44100:
2027 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302028 case 96000:
2029 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 break;
2031 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002032 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 }
2034
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002035 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036}
2037
2038static size_t get_input_buffer_size(uint32_t sample_rate,
2039 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002040 int channel_count,
2041 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042{
2043 size_t size = 0;
2044
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002045 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2046 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002048 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002049 if (is_low_latency)
2050 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302051
2052 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002054 /* make sure the size is multiple of 32 bytes
2055 * At 48 kHz mono 16-bit PCM:
2056 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2057 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2058 */
2059 size += 0x1f;
2060 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002061
2062 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063}
2064
Ashish Jain5106d362016-05-11 19:23:33 +05302065static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2066{
2067 uint64_t actual_frames_rendered = 0;
2068 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2069
2070 /* This adjustment accounts for buffering after app processor.
2071 * It is based on estimated DSP latency per use case, rather than exact.
2072 */
2073 int64_t platform_latency = platform_render_latency(out->usecase) *
2074 out->sample_rate / 1000000LL;
2075
2076 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2077 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2078 * hence only estimate.
2079 */
2080 int64_t signed_frames = out->written - kernel_buffer_size;
2081
2082 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2083
2084 if (signed_frames > 0)
2085 actual_frames_rendered = signed_frames;
2086
2087 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2088 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2089 (long long int)out->written, (int)kernel_buffer_size,
2090 audio_bytes_per_sample(out->compr_config.codec->format),
2091 popcount(out->channel_mask));
2092
2093 return actual_frames_rendered;
2094}
2095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2097{
2098 struct stream_out *out = (struct stream_out *)stream;
2099
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101}
2102
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002103static int out_set_sample_rate(struct audio_stream *stream __unused,
2104 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105{
2106 return -ENOSYS;
2107}
2108
2109static size_t out_get_buffer_size(const struct audio_stream *stream)
2110{
2111 struct stream_out *out = (struct stream_out *)stream;
2112
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002113 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002115 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2116 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002118 return out->config.period_size *
2119 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120}
2121
2122static uint32_t out_get_channels(const struct audio_stream *stream)
2123{
2124 struct stream_out *out = (struct stream_out *)stream;
2125
2126 return out->channel_mask;
2127}
2128
2129static audio_format_t out_get_format(const struct audio_stream *stream)
2130{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 struct stream_out *out = (struct stream_out *)stream;
2132
2133 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134}
2135
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002136static int out_set_format(struct audio_stream *stream __unused,
2137 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138{
2139 return -ENOSYS;
2140}
2141
2142static int out_standby(struct audio_stream *stream)
2143{
2144 struct stream_out *out = (struct stream_out *)stream;
2145 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302147 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2148 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002149 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2150 /* Ignore standby in case of voip call because the voip output
2151 * stream is closed in adev_close_output_stream()
2152 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302153 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002154 return 0;
2155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002157 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002159 if (adev->adm_deregister_stream)
2160 adev->adm_deregister_stream(adev->adm_data, out->handle);
2161
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002162 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002164 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 if (out->pcm) {
2166 pcm_close(out->pcm);
2167 out->pcm = NULL;
2168 }
2169 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002170 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302172 out->send_next_track_params = false;
2173 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002174 out->gapless_mdata.encoder_delay = 0;
2175 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176 if (out->compr != NULL) {
2177 compress_close(out->compr);
2178 out->compr = NULL;
2179 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002182 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 }
2184 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302185 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 return 0;
2187}
2188
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002189static int out_dump(const struct audio_stream *stream __unused,
2190 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191{
2192 return 0;
2193}
2194
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002195static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2196{
2197 int ret = 0;
2198 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002199
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002200 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002201 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202 return -EINVAL;
2203 }
2204
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302205 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002206
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002207 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2208 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302209 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002210 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002211 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2212 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302213 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002214 }
2215
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002216 ALOGV("%s new encoder delay %u and padding %u", __func__,
2217 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2218
2219 return 0;
2220}
2221
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002222static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2223{
2224 return out == adev->primary_output || out == adev->voice_tx_output;
2225}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2228{
2229 struct stream_out *out = (struct stream_out *)stream;
2230 struct audio_device *adev = out->dev;
2231 struct str_parms *parms;
2232 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002233 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234
sangwoobc677242013-08-08 16:53:43 +09002235 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002236 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302238 if (!parms)
2239 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002240 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2241 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002243 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002244 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002246 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302247 * When HDMI cable is unplugged/usb hs is disconnected the
2248 * music playback is paused and the policy manager sends routing=0
2249 * But the audioflingercontinues to write data until standby time
2250 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002251 * Avoid this by routing audio to speaker until standby.
2252 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302253 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2254 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002256 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002257 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 }
2259
2260 /*
2261 * select_devices() call below switches all the usecases on the same
2262 * backend to the new device. Refer to check_usecases_codec_backend() in
2263 * the select_devices(). But how do we undo this?
2264 *
2265 * For example, music playback is active on headset (deep-buffer usecase)
2266 * and if we go to ringtones and select a ringtone, low-latency usecase
2267 * will be started on headset+speaker. As we can't enable headset+speaker
2268 * and headset devices at the same time, select_devices() switches the music
2269 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2270 * So when the ringtone playback is completed, how do we undo the same?
2271 *
2272 * We are relying on the out_set_parameters() call on deep-buffer output,
2273 * once the ringtone playback is ended.
2274 * NOTE: We should not check if the current devices are same as new devices.
2275 * Because select_devices() must be called to switch back the music
2276 * playback to headset.
2277 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002278 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279 out->devices = val;
2280
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302281 if (!out->standby) {
2282 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2283 adev->perf_lock_opts,
2284 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002285 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302286 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2287 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002288
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002289 if (output_drives_call(adev, out)) {
2290 if(!voice_is_in_call(adev)) {
2291 if (adev->mode == AUDIO_MODE_IN_CALL) {
2292 adev->current_call_output = out;
2293 ret = voice_start_call(adev);
2294 }
2295 } else {
2296 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002297 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002298 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002299 }
2300 }
2301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002303 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002305
2306 if (out == adev->primary_output) {
2307 pthread_mutex_lock(&adev->lock);
2308 audio_extn_set_parameters(adev, parms);
2309 pthread_mutex_unlock(&adev->lock);
2310 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002311 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002312 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002313 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002314
2315 audio_extn_dts_create_state_notifier_node(out->usecase);
2316 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2317 popcount(out->channel_mask),
2318 out->playback_started);
2319
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002320 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002321 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302324error:
Eric Laurent994a6932013-07-17 11:51:42 -07002325 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326 return ret;
2327}
2328
2329static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2330{
2331 struct stream_out *out = (struct stream_out *)stream;
2332 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002333 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 char value[256];
2335 struct str_parms *reply = str_parms_create();
2336 size_t i, j;
2337 int ret;
2338 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002339
2340 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002341 if (reply) {
2342 str_parms_destroy(reply);
2343 }
2344 if (query) {
2345 str_parms_destroy(query);
2346 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002347 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2348 return NULL;
2349 }
2350
Eric Laurent994a6932013-07-17 11:51:42 -07002351 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2353 if (ret >= 0) {
2354 value[0] = '\0';
2355 i = 0;
2356 while (out->supported_channel_masks[i] != 0) {
2357 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2358 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2359 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002360 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002362 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 first = false;
2364 break;
2365 }
2366 }
2367 i++;
2368 }
2369 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2370 str = str_parms_to_str(reply);
2371 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002372 voice_extn_out_get_parameters(out, query, reply);
2373 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002374 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002375 free(str);
2376 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002379
Alexy Joseph62142aa2015-11-16 15:10:34 -08002380
2381 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2382 if (ret >= 0) {
2383 value[0] = '\0';
2384 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2385 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302386 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002387 } else {
2388 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302389 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002390 }
2391 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002392 if (str)
2393 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002394 str = str_parms_to_str(reply);
2395 }
2396
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002397 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2398 if (ret >= 0) {
2399 value[0] = '\0';
2400 i = 0;
2401 first = true;
2402 while (out->supported_formats[i] != 0) {
2403 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2404 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2405 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002406 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002407 }
2408 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2409 first = false;
2410 break;
2411 }
2412 }
2413 i++;
2414 }
2415 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002416 if (str)
2417 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002418 str = str_parms_to_str(reply);
2419 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002420
2421 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2422 if (ret >= 0) {
2423 value[0] = '\0';
2424 i = 0;
2425 first = true;
2426 while (out->supported_sample_rates[i] != 0) {
2427 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2428 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2429 if (!first) {
2430 strlcat(value, "|", sizeof(value));
2431 }
2432 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2433 first = false;
2434 break;
2435 }
2436 }
2437 i++;
2438 }
2439 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2440 if (str)
2441 free(str);
2442 str = str_parms_to_str(reply);
2443 }
2444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 str_parms_destroy(query);
2446 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002447 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 return str;
2449}
2450
2451static uint32_t out_get_latency(const struct audio_stream_out *stream)
2452{
2453 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002454 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455
Alexy Josephaa54c872014-12-03 02:46:47 -08002456 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002457 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002458 } else {
2459 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002460 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002461 }
2462
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302463 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002464 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465}
2466
2467static int out_set_volume(struct audio_stream_out *stream, float left,
2468 float right)
2469{
Eric Laurenta9024de2013-04-04 09:19:12 -07002470 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 int volume[2];
2472
Eric Laurenta9024de2013-04-04 09:19:12 -07002473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2474 /* only take left channel into account: the API is for stereo anyway */
2475 out->muted = (left == 0.0f);
2476 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002477 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002478 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002479 /*
2480 * Set mute or umute on HDMI passthrough stream.
2481 * Only take left channel into account.
2482 * Mute is 0 and unmute 1
2483 */
2484 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2485 } else {
2486 char mixer_ctl_name[128];
2487 struct audio_device *adev = out->dev;
2488 struct mixer_ctl *ctl;
2489 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002490 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002492 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2493 "Compress Playback %d Volume", pcm_device_id);
2494 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2495 if (!ctl) {
2496 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2497 __func__, mixer_ctl_name);
2498 return -EINVAL;
2499 }
2500 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2501 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2502 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2503 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 return -ENOSYS;
2508}
2509
2510static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2511 size_t bytes)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302515 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002516 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002518 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302519
Naresh Tanniru80659832014-06-04 18:17:56 +05302520 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002521
Ashish Jainbbce4322016-02-16 13:25:27 +05302522 if (is_offload_usecase(out->usecase)) {
2523 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302524 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2525 pthread_mutex_unlock(&out->lock);
2526 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302527 } else {
2528 /* increase written size during SSR to avoid mismatch
2529 * with the written frames count in AF
2530 */
2531 out->written += bytes / (out->config.channels * sizeof(short));
2532 ALOGD(" %s: sound card is not active/SSR state", __func__);
2533 ret= -EIO;
2534 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302535 }
2536 }
2537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002539 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002541 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2542 ret = voice_extn_compress_voip_start_output_stream(out);
2543 else
2544 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002548 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 goto exit;
2550 }
vivek mehta446c3962015-09-14 10:57:35 -07002551 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002552 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554
Ashish Jain81eb2a82015-05-13 10:52:34 +05302555 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002556 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302557 adev->is_channel_status_set = true;
2558 }
2559
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002560 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002561 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002562 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002563 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002564 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2565 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302566 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2567 ALOGD("copl(%p):send next track params in gapless", out);
2568 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2569 out->send_next_track_params = false;
2570 out->is_compr_metadata_avail = false;
2571 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002572 }
2573
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302575 if (ret < 0)
2576 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302577 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002578 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302579 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302581 } else if (-ENETRESET == ret) {
2582 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2583 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2584 pthread_mutex_unlock(&out->lock);
2585 out_standby(&out->stream.common);
2586 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002587 }
Ashish Jain5106d362016-05-11 19:23:33 +05302588 if ( ret == (ssize_t)bytes && !out->non_blocking)
2589 out->written += bytes;
2590
Naresh Tanniru80659832014-06-04 18:17:56 +05302591 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002592 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002593 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 out->playback_started = 1;
2595 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002596
2597 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2598 popcount(out->channel_mask),
2599 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600 }
2601 pthread_mutex_unlock(&out->lock);
2602 return ret;
2603 } else {
2604 if (out->pcm) {
2605 if (out->muted)
2606 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002607
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302608 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002609
2610 if (adev->adm_request_focus)
2611 adev->adm_request_focus(adev->adm_data, out->handle);
2612
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002613 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2614 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2615 else
2616 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002617
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302618 if (ret < 0)
2619 ret = -errno;
2620 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002621 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002622
2623 if (adev->adm_abandon_focus)
2624 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 }
2627
2628exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302629 /* ToDo: There may be a corner case when SSR happens back to back during
2630 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302631 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302632 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 }
2634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 pthread_mutex_unlock(&out->lock);
2636
2637 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002638 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002639 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302640 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302641 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302642 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302643 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302644 out->standby = true;
2645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302647 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302648 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 }
2650 return bytes;
2651}
2652
2653static int out_get_render_position(const struct audio_stream_out *stream,
2654 uint32_t *dsp_frames)
2655{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302657 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002658
2659 if (dsp_frames == NULL)
2660 return -EINVAL;
2661
2662 *dsp_frames = 0;
2663 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002664 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302665
2666 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2667 * this operation and adev_close_output_stream(where out gets reset).
2668 */
2669 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2670 *dsp_frames = get_actual_pcm_frames_rendered(out);
2671 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2672 return 0;
2673 }
2674
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002675 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302676 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302677 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302679 if (ret < 0)
2680 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002681 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302682 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 }
2684 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302685 if (-ENETRESET == ret) {
2686 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2687 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2688 return -EINVAL;
2689 } else if(ret < 0) {
2690 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2691 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302692 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2693 /*
2694 * Handle corner case where compress session is closed during SSR
2695 * and timestamp is queried
2696 */
2697 ALOGE(" ERROR: sound card not active, return error");
2698 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302699 } else {
2700 return 0;
2701 }
Zhou Song32a556e2015-05-05 10:46:56 +08002702 } else if (audio_is_linear_pcm(out->format)) {
2703 *dsp_frames = out->written;
2704 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 } else
2706 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707}
2708
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002709static int out_add_audio_effect(const struct audio_stream *stream __unused,
2710 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711{
2712 return 0;
2713}
2714
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002715static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2716 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717{
2718 return 0;
2719}
2720
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002721static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2722 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
2724 return -EINVAL;
2725}
2726
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002727static int out_get_presentation_position(const struct audio_stream_out *stream,
2728 uint64_t *frames, struct timespec *timestamp)
2729{
2730 struct stream_out *out = (struct stream_out *)stream;
2731 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002732 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002733
Ashish Jain5106d362016-05-11 19:23:33 +05302734 /* below piece of code is not guarded against any lock because audioFliner serializes
2735 * this operation and adev_close_output_stream( where out gets reset).
2736 */
2737 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2738 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2739 *frames = get_actual_pcm_frames_rendered(out);
2740 /* this is the best we can do */
2741 clock_gettime(CLOCK_MONOTONIC, timestamp);
2742 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2743 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2744 return 0;
2745 }
2746
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002747 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002748
Ashish Jain5106d362016-05-11 19:23:33 +05302749 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2750 ret = compress_get_tstamp(out->compr, &dsp_frames,
2751 &out->sample_rate);
2752 ALOGVV("%s rendered frames %ld sample_rate %d",
2753 __func__, dsp_frames, out->sample_rate);
2754 *frames = dsp_frames;
2755 if (ret < 0)
2756 ret = -errno;
2757 if (-ENETRESET == ret) {
2758 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2759 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2760 ret = -EINVAL;
2761 } else
2762 ret = 0;
2763 /* this is the best we can do */
2764 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002765 } else {
2766 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002767 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002768 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2769 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002770 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002771 // This adjustment accounts for buffering after app processor.
2772 // It is based on estimated DSP latency per use case, rather than exact.
2773 signed_frames -=
2774 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2775
Eric Laurent949a0892013-09-20 09:20:13 -07002776 // It would be unusual for this value to be negative, but check just in case ...
2777 if (signed_frames >= 0) {
2778 *frames = signed_frames;
2779 ret = 0;
2780 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002781 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302782 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2783 *frames = out->written;
2784 clock_gettime(CLOCK_MONOTONIC, timestamp);
2785 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002786 }
2787 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002788 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002789 return ret;
2790}
2791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002792static int out_set_callback(struct audio_stream_out *stream,
2793 stream_callback_t callback, void *cookie)
2794{
2795 struct stream_out *out = (struct stream_out *)stream;
2796
2797 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->offload_callback = callback;
2800 out->offload_cookie = cookie;
2801 pthread_mutex_unlock(&out->lock);
2802 return 0;
2803}
2804
2805static int out_pause(struct audio_stream_out* stream)
2806{
2807 struct stream_out *out = (struct stream_out *)stream;
2808 int status = -ENOSYS;
2809 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002810 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002811 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002812 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302814 struct audio_device *adev = out->dev;
2815 int snd_scard_state = get_snd_card_state(adev);
2816
2817 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2818 status = compress_pause(out->compr);
2819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002821
Mingming Yin21854652016-04-13 11:54:02 -07002822 if (audio_extn_passthru_is_active()) {
2823 ALOGV("offload use case, pause passthru");
2824 audio_extn_passthru_on_pause(out);
2825 }
2826
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302827 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002828 audio_extn_dts_notify_playback_state(out->usecase, 0,
2829 out->sample_rate, popcount(out->channel_mask),
2830 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 }
2832 pthread_mutex_unlock(&out->lock);
2833 }
2834 return status;
2835}
2836
2837static int out_resume(struct audio_stream_out* stream)
2838{
2839 struct stream_out *out = (struct stream_out *)stream;
2840 int status = -ENOSYS;
2841 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002842 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002843 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002845 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302847 struct audio_device *adev = out->dev;
2848 int snd_scard_state = get_snd_card_state(adev);
2849
Mingming Yin21854652016-04-13 11:54:02 -07002850 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2851 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2852 pthread_mutex_lock(&out->dev->lock);
2853 ALOGV("offload resume, check and set hdmi backend again");
2854 check_and_set_hdmi_backend(out);
2855 pthread_mutex_unlock(&out->dev->lock);
2856 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302857 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002858 }
2859 if (!status) {
2860 out->offload_state = OFFLOAD_STATE_PLAYING;
2861 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302862 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002863 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2864 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 }
2866 pthread_mutex_unlock(&out->lock);
2867 }
2868 return status;
2869}
2870
2871static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2872{
2873 struct stream_out *out = (struct stream_out *)stream;
2874 int status = -ENOSYS;
2875 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002876 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002877 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2879 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2880 else
2881 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2882 pthread_mutex_unlock(&out->lock);
2883 }
2884 return status;
2885}
2886
2887static int out_flush(struct audio_stream_out* stream)
2888{
2889 struct stream_out *out = (struct stream_out *)stream;
2890 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002891 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002892 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002893 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302895 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002897 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 return 0;
2899 }
2900 return -ENOSYS;
2901}
2902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903/** audio_stream_in implementation **/
2904static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2905{
2906 struct stream_in *in = (struct stream_in *)stream;
2907
2908 return in->config.rate;
2909}
2910
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002911static int in_set_sample_rate(struct audio_stream *stream __unused,
2912 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913{
2914 return -ENOSYS;
2915}
2916
2917static size_t in_get_buffer_size(const struct audio_stream *stream)
2918{
2919 struct stream_in *in = (struct stream_in *)stream;
2920
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002921 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2922 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002923 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2924 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002925
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002926 return in->config.period_size *
2927 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928}
2929
2930static uint32_t in_get_channels(const struct audio_stream *stream)
2931{
2932 struct stream_in *in = (struct stream_in *)stream;
2933
2934 return in->channel_mask;
2935}
2936
2937static audio_format_t in_get_format(const struct audio_stream *stream)
2938{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002939 struct stream_in *in = (struct stream_in *)stream;
2940
2941 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942}
2943
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002944static int in_set_format(struct audio_stream *stream __unused,
2945 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946{
2947 return -ENOSYS;
2948}
2949
2950static int in_standby(struct audio_stream *stream)
2951{
2952 struct stream_in *in = (struct stream_in *)stream;
2953 struct audio_device *adev = in->dev;
2954 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302955 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2956 stream, in->usecase, use_case_table[in->usecase]);
2957
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002958 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2959 /* Ignore standby in case of voip call because the voip input
2960 * stream is closed in adev_close_input_stream()
2961 */
2962 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2963 return status;
2964 }
2965
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002966 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002967 if (!in->standby && in->is_st_session) {
2968 ALOGD("%s: sound trigger pcm stop lab", __func__);
2969 audio_extn_sound_trigger_stop_lab(in);
2970 in->standby = 1;
2971 }
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002974 if (adev->adm_deregister_stream)
2975 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2976
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002977 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002979 if (in->pcm) {
2980 pcm_close(in->pcm);
2981 in->pcm = NULL;
2982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002984 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 }
2986 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002987 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 return status;
2989}
2990
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002991static int in_dump(const struct audio_stream *stream __unused,
2992 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993{
2994 return 0;
2995}
2996
2997static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2998{
2999 struct stream_in *in = (struct stream_in *)stream;
3000 struct audio_device *adev = in->dev;
3001 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003003 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303005 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 parms = str_parms_create_str(kvpairs);
3007
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303008 if (!parms)
3009 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003010 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003011 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003012
3013 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3014 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 val = atoi(value);
3016 /* no audio source uses val == 0 */
3017 if ((in->source != val) && (val != 0)) {
3018 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003019 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3020 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3021 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003022 (in->config.rate == 8000 || in->config.rate == 16000 ||
3023 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003024 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003025 err = voice_extn_compress_voip_open_input_stream(in);
3026 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003027 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003028 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003029 }
3030 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 }
3032 }
3033
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003034 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3035 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003037 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 in->device = val;
3039 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003040 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003041 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 }
3043 }
3044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003046 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
3048 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303049error:
Eric Laurent994a6932013-07-17 11:51:42 -07003050 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 return ret;
3052}
3053
3054static char* in_get_parameters(const struct audio_stream *stream,
3055 const char *keys)
3056{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 struct stream_in *in = (struct stream_in *)stream;
3058 struct str_parms *query = str_parms_create_str(keys);
3059 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003060 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003061
3062 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003063 if (reply) {
3064 str_parms_destroy(reply);
3065 }
3066 if (query) {
3067 str_parms_destroy(query);
3068 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003069 ALOGE("in_get_parameters: failed to create query or reply");
3070 return NULL;
3071 }
3072
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 ALOGV("%s: enter: keys - %s", __func__, keys);
3074
3075 voice_extn_in_get_parameters(in, query, reply);
3076
3077 str = str_parms_to_str(reply);
3078 str_parms_destroy(query);
3079 str_parms_destroy(reply);
3080
3081 ALOGV("%s: exit: returns - %s", __func__, str);
3082 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083}
3084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003085static int in_set_gain(struct audio_stream_in *stream __unused,
3086 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087{
3088 return 0;
3089}
3090
3091static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3092 size_t bytes)
3093{
3094 struct stream_in *in = (struct stream_in *)stream;
3095 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303096 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303097 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303098 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003100 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303101
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003102 if (in->is_st_session) {
3103 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3104 /* Read from sound trigger HAL */
3105 audio_extn_sound_trigger_read(in, buffer, bytes);
3106 pthread_mutex_unlock(&in->lock);
3107 return bytes;
3108 }
3109
Ashish Jainbbce4322016-02-16 13:25:27 +05303110 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003111 ALOGD(" %s: sound card is not active/SSR state", __func__);
3112 ret= -EIO;;
3113 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303114 }
3115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003117 pthread_mutex_lock(&adev->lock);
3118 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3119 ret = voice_extn_compress_voip_start_input_stream(in);
3120 else
3121 ret = start_input_stream(in);
3122 pthread_mutex_unlock(&adev->lock);
3123 if (ret != 0) {
3124 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 }
3126 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003127 if (adev->adm_register_input_stream)
3128 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003131 if (adev->adm_request_focus)
3132 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303135 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003136 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303137 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003138 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303139 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003140 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303141 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003142 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303143 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3144 if (bytes % 4 == 0) {
3145 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3146 int_buf_stream = buffer;
3147 for (size_t itt=0; itt < bytes/4 ; itt++) {
3148 int_buf_stream[itt] >>= 8;
3149 }
3150 } else {
3151 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3152 ret = -EINVAL;
3153 goto exit;
3154 }
3155 } if (ret < 0) {
3156 ret = -errno;
3157 }
3158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 }
3160
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003161 if (adev->adm_abandon_focus)
3162 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 /*
3165 * Instead of writing zeroes here, we could trust the hardware
3166 * to always provide zeroes when muted.
3167 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303168 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3169 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 memset(buffer, 0, bytes);
3171
3172exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303173 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303174 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003175 if (-ENETRESET == ret)
3176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 pthread_mutex_unlock(&in->lock);
3179
3180 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303181 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303182 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303183 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303184 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303185 in->standby = true;
3186 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303187 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003189 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303190 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303191 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 }
3193 return bytes;
3194}
3195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003196static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197{
3198 return 0;
3199}
3200
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003201static int add_remove_audio_effect(const struct audio_stream *stream,
3202 effect_handle_t effect,
3203 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003205 struct stream_in *in = (struct stream_in *)stream;
3206 int status = 0;
3207 effect_descriptor_t desc;
3208
3209 status = (*effect)->get_descriptor(effect, &desc);
3210 if (status != 0)
3211 return status;
3212
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003213 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003214 pthread_mutex_lock(&in->dev->lock);
3215 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3216 in->enable_aec != enable &&
3217 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3218 in->enable_aec = enable;
3219 if (!in->standby)
3220 select_devices(in->dev, in->usecase);
3221 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003222 if (in->enable_ns != enable &&
3223 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3224 in->enable_ns = enable;
3225 if (!in->standby)
3226 select_devices(in->dev, in->usecase);
3227 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003228 pthread_mutex_unlock(&in->dev->lock);
3229 pthread_mutex_unlock(&in->lock);
3230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 return 0;
3232}
3233
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003234static int in_add_audio_effect(const struct audio_stream *stream,
3235 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236{
Eric Laurent994a6932013-07-17 11:51:42 -07003237 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003238 return add_remove_audio_effect(stream, effect, true);
3239}
3240
3241static int in_remove_audio_effect(const struct audio_stream *stream,
3242 effect_handle_t effect)
3243{
Eric Laurent994a6932013-07-17 11:51:42 -07003244 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003245 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246}
3247
3248static int adev_open_output_stream(struct audio_hw_device *dev,
3249 audio_io_handle_t handle,
3250 audio_devices_t devices,
3251 audio_output_flags_t flags,
3252 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 struct audio_stream_out **stream_out,
3254 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255{
3256 struct audio_device *adev = (struct audio_device *)dev;
3257 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303258 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003259 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303262
3263 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3264 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003265 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303266 return -EINVAL;
3267 }
3268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3270
Mingming Yin3a941d42016-02-17 18:08:05 -08003271 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3272 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303273 devices, flags, &out->stream);
3274
3275
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003276 if (!out) {
3277 return -ENOMEM;
3278 }
3279
Haynes Mathew George204045b2015-02-25 20:32:03 -08003280 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003281 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003282 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 if (devices == AUDIO_DEVICE_NONE)
3285 devices = AUDIO_DEVICE_OUT_SPEAKER;
3286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 out->flags = flags;
3288 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003289 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003290 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003291 out->sample_rate = config->sample_rate;
3292 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3293 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003294 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003295 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003296 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297
Mingming Yin3a941d42016-02-17 18:08:05 -08003298 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3299 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3300 pthread_mutex_lock(&adev->lock);
3301 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3302 ret = read_hdmi_sink_caps(out);
3303 pthread_mutex_unlock(&adev->lock);
3304 if (ret != 0) {
3305 if (ret == -ENOSYS) {
3306 /* ignore and go with default */
3307 ret = 0;
3308 } else {
3309 ALOGE("error reading hdmi sink caps");
3310 goto error_open;
3311 }
3312 }
3313 }
3314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003316 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303317 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3318 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003319 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3320 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3321
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003322 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003323 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3324 /*
3325 * Do not handle stereo output in Multi-channel cases
3326 * Stereo case is handled in normal playback path
3327 */
3328 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3329 ret = AUDIO_CHANNEL_OUT_STEREO;
3330 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003331
3332 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3333 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003334 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003335 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003336 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003337
3338 if (config->sample_rate == 0)
3339 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3340 if (config->channel_mask == 0)
3341 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003342 if (config->format == 0)
3343 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003344
3345 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003347 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3349 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003351 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003353 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3354 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003355 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003356 ret = voice_extn_compress_voip_open_output_stream(out);
3357 if (ret != 0) {
3358 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3359 __func__, ret);
3360 goto error_open;
3361 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003362 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3363 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3364
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3366 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3367 ALOGE("%s: Unsupported Offload information", __func__);
3368 ret = -EINVAL;
3369 goto error_open;
3370 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003371
Mingming Yin3a941d42016-02-17 18:08:05 -08003372 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003373 if(config->offload_info.format == 0)
3374 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003375 if (config->offload_info.sample_rate == 0)
3376 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003377 }
3378
Mingming Yin90310102013-11-13 16:57:00 -08003379 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003380 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003381 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 ret = -EINVAL;
3383 goto error_open;
3384 }
3385
3386 out->compr_config.codec = (struct snd_codec *)
3387 calloc(1, sizeof(struct snd_codec));
3388
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003389 if (!out->compr_config.codec) {
3390 ret = -ENOMEM;
3391 goto error_open;
3392 }
3393
vivek mehta0ea887a2015-08-26 14:01:20 -07003394 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303395 out->stream.pause = out_pause;
3396 out->stream.flush = out_flush;
3397 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003398 out->usecase = get_offload_usecase(adev, true);
3399 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003400 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003401 out->stream.set_callback = out_set_callback;
3402 out->stream.pause = out_pause;
3403 out->stream.resume = out_resume;
3404 out->stream.drain = out_drain;
3405 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003406 out->usecase = get_offload_usecase(adev, false);
3407 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003408 }
vivek mehta446c3962015-09-14 10:57:35 -07003409
3410 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003411 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3412 config->format == 0 && config->sample_rate == 0 &&
3413 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003414 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003415 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3416 } else {
3417 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3418 ret = -EEXIST;
3419 goto error_open;
3420 }
vivek mehta446c3962015-09-14 10:57:35 -07003421 }
3422
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003423 if (config->offload_info.channel_mask)
3424 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003425 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003427 config->offload_info.channel_mask = config->channel_mask;
3428 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003429 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 out->sample_rate = config->offload_info.sample_rate;
3431
Mingming Yin3ee55c62014-08-04 14:23:35 -07003432 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003434 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003435 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003436 audio_extn_dolby_get_snd_codec_id(adev, out,
3437 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003438 else
3439 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003441
Ashish Jain5106d362016-05-11 19:23:33 +05303442 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003443 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003444 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303445 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Mingming Yin21854652016-04-13 11:54:02 -07003446 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003447 out->compr_config.fragment_size =
3448 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303449 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003450 } else {
3451 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003452 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303453 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003454 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003455 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003456 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 out->compr_config.codec->bit_rate =
3458 config->offload_info.bit_rate;
3459 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003460 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303462 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003463 /*TODO: Do we need to change it for passthrough */
3464 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465
Manish Dewangana6fc5442015-08-24 20:30:31 +05303466 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3467 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3468 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3469 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003470 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3471 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303472 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3473 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3474 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003475 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003476
Amit Shekhar6f461b12014-08-01 14:52:58 -07003477 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303478 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3481 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003482
Alexy Josephaa54c872014-12-03 02:46:47 -08003483
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003484 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303485 out->send_next_track_params = false;
3486 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003487 out->offload_state = OFFLOAD_STATE_IDLE;
3488 out->playback_started = 0;
3489
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003490 audio_extn_dts_create_state_notifier_node(out->usecase);
3491
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 create_offload_callback_thread(out);
3493 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3494 __func__, config->offload_info.version,
3495 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303496
3497 /* Disable gapless if any of the following is true
3498 * passthrough playback
3499 * AV playback
3500 * Direct PCM playback
3501 */
3502 if (audio_extn_dolby_is_passthrough_stream(out) ||
3503 config->offload_info.has_video ||
3504 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3505 check_and_set_gapless_mode(adev, false);
3506 } else
3507 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003508
3509 if (audio_extn_dolby_is_passthrough_stream(out)) {
3510 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3511 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003512 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303513 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003514 if (ret != 0) {
3515 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3516 __func__, ret);
3517 goto error_open;
3518 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003519 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3520 if (config->sample_rate == 0)
3521 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3522 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3523 config->sample_rate != 8000) {
3524 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3525 ret = -EINVAL;
3526 goto error_open;
3527 }
3528 out->sample_rate = config->sample_rate;
3529 out->config.rate = config->sample_rate;
3530 if (config->format == AUDIO_FORMAT_DEFAULT)
3531 config->format = AUDIO_FORMAT_PCM_16_BIT;
3532 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3533 config->format = AUDIO_FORMAT_PCM_16_BIT;
3534 ret = -EINVAL;
3535 goto error_open;
3536 }
3537 out->format = config->format;
3538 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3539 out->config = pcm_config_afe_proxy_playback;
3540 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003541 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3542 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3543 out->config = pcm_config_low_latency;
3544 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003545 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003546 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3548 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003550 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3551 format = AUDIO_FORMAT_PCM_16_BIT;
3552 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3553 out->config = pcm_config_deep_buffer;
3554 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003555 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003556 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003557 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003558 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003559 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003560 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 }
3562
Mingming Yin21854652016-04-13 11:54:02 -07003563 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3564 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003565 /* TODO remove this hardcoding and check why width is zero*/
3566 if (out->bit_width == 0)
3567 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003568 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3569 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003570 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303571 out->bit_width, out->channel_mask,
3572 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003573 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3574 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3575 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003576 if(adev->primary_output == NULL)
3577 adev->primary_output = out;
3578 else {
3579 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003580 ret = -EEXIST;
3581 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003582 }
3583 }
3584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 /* Check if this usecase is already existing */
3586 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003587 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3588 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003591 ret = -EEXIST;
3592 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 }
3594 pthread_mutex_unlock(&adev->lock);
3595
3596 out->stream.common.get_sample_rate = out_get_sample_rate;
3597 out->stream.common.set_sample_rate = out_set_sample_rate;
3598 out->stream.common.get_buffer_size = out_get_buffer_size;
3599 out->stream.common.get_channels = out_get_channels;
3600 out->stream.common.get_format = out_get_format;
3601 out->stream.common.set_format = out_set_format;
3602 out->stream.common.standby = out_standby;
3603 out->stream.common.dump = out_dump;
3604 out->stream.common.set_parameters = out_set_parameters;
3605 out->stream.common.get_parameters = out_get_parameters;
3606 out->stream.common.add_audio_effect = out_add_audio_effect;
3607 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3608 out->stream.get_latency = out_get_latency;
3609 out->stream.set_volume = out_set_volume;
3610 out->stream.write = out_write;
3611 out->stream.get_render_position = out_get_render_position;
3612 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003613 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003616 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003617 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618
3619 config->format = out->stream.common.get_format(&out->stream.common);
3620 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3621 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3622
3623 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303624 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003625 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003626
3627 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3628 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3629 popcount(out->channel_mask), out->playback_started);
3630
Eric Laurent994a6932013-07-17 11:51:42 -07003631 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003633
3634error_open:
3635 free(out);
3636 *stream_out = NULL;
3637 ALOGD("%s: exit: ret %d", __func__, ret);
3638 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639}
3640
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003641static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 struct audio_stream_out *stream)
3643{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003644 struct stream_out *out = (struct stream_out *)stream;
3645 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003646 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003647
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303648 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3649
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003650 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303651 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003652 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303653 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003654 if(ret != 0)
3655 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3656 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003657 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003658 out_standby(&stream->common);
3659
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003660 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003661 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003663 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 if (out->compr_config.codec != NULL)
3665 free(out->compr_config.codec);
3666 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003667
3668 if (adev->voice_tx_output == out)
3669 adev->voice_tx_output = NULL;
3670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671 pthread_cond_destroy(&out->cond);
3672 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003674 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675}
3676
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003677static void close_compress_sessions(struct audio_device *adev)
3678{
Mingming Yin7b762e72015-03-04 13:47:32 -08003679 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303680 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003681 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003682 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303683
3684 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003685 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303686 if (is_offload_usecase(usecase->id)) {
3687 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003688 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3689 out = usecase->stream.out;
3690 pthread_mutex_unlock(&adev->lock);
3691 out_standby(&out->stream.common);
3692 pthread_mutex_lock(&adev->lock);
3693 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303694 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003695 }
3696 pthread_mutex_unlock(&adev->lock);
3697}
3698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3700{
3701 struct audio_device *adev = (struct audio_device *)dev;
3702 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003704 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003705 int ret;
3706 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003708 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303711 if (!parms)
3712 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003713 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3714 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303715 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303716 if (strstr(snd_card_status, "OFFLINE")) {
3717 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303718 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003719 //close compress sessions on OFFLINE status
3720 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303721 } else if (strstr(snd_card_status, "ONLINE")) {
3722 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303723 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003724 //send dts hpx license if enabled
3725 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303726 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303727 }
3728
3729 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003730 status = voice_set_parameters(adev, parms);
3731 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003732 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003734 status = platform_set_parameters(adev->platform, parms);
3735 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003736 goto done;
3737
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003738 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3739 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003740 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3742 adev->bluetooth_nrec = true;
3743 else
3744 adev->bluetooth_nrec = false;
3745 }
3746
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003747 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3748 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3750 adev->screen_off = false;
3751 else
3752 adev->screen_off = true;
3753 }
3754
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003755 ret = str_parms_get_int(parms, "rotation", &val);
3756 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003757 bool reverse_speakers = false;
3758 switch(val) {
3759 // FIXME: note that the code below assumes that the speakers are in the correct placement
3760 // relative to the user when the device is rotated 90deg from its default rotation. This
3761 // assumption is device-specific, not platform-specific like this code.
3762 case 270:
3763 reverse_speakers = true;
3764 break;
3765 case 0:
3766 case 90:
3767 case 180:
3768 break;
3769 default:
3770 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003771 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003772 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003773 if (status == 0) {
3774 if (adev->speaker_lr_swap != reverse_speakers) {
3775 adev->speaker_lr_swap = reverse_speakers;
3776 // only update the selected device if there is active pcm playback
3777 struct audio_usecase *usecase;
3778 struct listnode *node;
3779 list_for_each(node, &adev->usecase_list) {
3780 usecase = node_to_item(node, struct audio_usecase, list);
3781 if (usecase->type == PCM_PLAYBACK) {
3782 select_devices(adev, usecase->id);
3783 break;
3784 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003785 }
3786 }
3787 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003788 }
3789
Mingming Yin514a8bc2014-07-29 15:22:21 -07003790 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3791 if (ret >= 0) {
3792 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3793 adev->bt_wb_speech_enabled = true;
3794 else
3795 adev->bt_wb_speech_enabled = false;
3796 }
3797
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003798 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3799 if (ret >= 0) {
3800 val = atoi(value);
3801 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3802 ALOGV("cache new edid");
3803 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003804 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3805 /*
3806 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3807 * Per AudioPolicyManager, USB device is higher priority than WFD.
3808 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3809 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3810 * starting voice call on USB
3811 */
3812 ALOGV("detected USB connect .. disable proxy");
3813 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003814 }
3815 }
3816
3817 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3818 if (ret >= 0) {
3819 val = atoi(value);
3820 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3821 ALOGV("invalidate cached edid");
3822 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003823 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3824 ALOGV("detected USB disconnect .. enable proxy");
3825 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003826 }
3827 }
3828
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003829 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003830
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003831done:
3832 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003833 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303834error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003835 ALOGV("%s: exit with code(%d)", __func__, status);
3836 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837}
3838
3839static char* adev_get_parameters(const struct audio_hw_device *dev,
3840 const char *keys)
3841{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003842 struct audio_device *adev = (struct audio_device *)dev;
3843 struct str_parms *reply = str_parms_create();
3844 struct str_parms *query = str_parms_create_str(keys);
3845 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303846 char value[256] = {0};
3847 int ret = 0;
3848
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003849 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003850 if (reply) {
3851 str_parms_destroy(reply);
3852 }
3853 if (query) {
3854 str_parms_destroy(query);
3855 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003856 ALOGE("adev_get_parameters: failed to create query or reply");
3857 return NULL;
3858 }
3859
Naresh Tannirud7205b62014-06-20 02:54:48 +05303860 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3861 sizeof(value));
3862 if (ret >=0) {
3863 int val = 1;
3864 pthread_mutex_lock(&adev->snd_card_status.lock);
3865 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3866 val = 0;
3867 pthread_mutex_unlock(&adev->snd_card_status.lock);
3868 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3869 goto exit;
3870 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003871
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003872 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003873 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003874 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003875 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303876 pthread_mutex_unlock(&adev->lock);
3877
Naresh Tannirud7205b62014-06-20 02:54:48 +05303878exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003879 str = str_parms_to_str(reply);
3880 str_parms_destroy(query);
3881 str_parms_destroy(reply);
3882
3883 ALOGV("%s: exit: returns - %s", __func__, str);
3884 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885}
3886
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003887static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888{
3889 return 0;
3890}
3891
3892static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3893{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003894 int ret;
3895 struct audio_device *adev = (struct audio_device *)dev;
3896 pthread_mutex_lock(&adev->lock);
3897 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003898 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003899 pthread_mutex_unlock(&adev->lock);
3900 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901}
3902
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003903static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3904 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905{
3906 return -ENOSYS;
3907}
3908
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003909static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3910 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911{
3912 return -ENOSYS;
3913}
3914
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003915static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3916 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917{
3918 return -ENOSYS;
3919}
3920
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003921static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3922 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
3924 return -ENOSYS;
3925}
3926
3927static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3928{
3929 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 pthread_mutex_lock(&adev->lock);
3932 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003933 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003935 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003936 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003937 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003938 adev->current_call_output = NULL;
3939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 }
3941 pthread_mutex_unlock(&adev->lock);
3942 return 0;
3943}
3944
3945static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3946{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003947 int ret;
3948
3949 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003950 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003951 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3952 pthread_mutex_unlock(&adev->lock);
3953
3954 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955}
3956
3957static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3958{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003959 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 return 0;
3961}
3962
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003963static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 const struct audio_config *config)
3965{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003966 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003968 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3969 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970}
3971
3972static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003973 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974 audio_devices_t devices,
3975 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003976 struct audio_stream_in **stream_in,
3977 audio_input_flags_t flags __unused,
3978 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003979 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980{
3981 struct audio_device *adev = (struct audio_device *)dev;
3982 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003983 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003984 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003985 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 *stream_in = NULL;
3988 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3989 return -EINVAL;
3990
3991 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003992
3993 if (!in) {
3994 ALOGE("failed to allocate input stream");
3995 return -ENOMEM;
3996 }
3997
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303998 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303999 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4000 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004001 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004002 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 in->stream.common.get_sample_rate = in_get_sample_rate;
4005 in->stream.common.set_sample_rate = in_set_sample_rate;
4006 in->stream.common.get_buffer_size = in_get_buffer_size;
4007 in->stream.common.get_channels = in_get_channels;
4008 in->stream.common.get_format = in_get_format;
4009 in->stream.common.set_format = in_set_format;
4010 in->stream.common.standby = in_standby;
4011 in->stream.common.dump = in_dump;
4012 in->stream.common.set_parameters = in_set_parameters;
4013 in->stream.common.get_parameters = in_get_parameters;
4014 in->stream.common.add_audio_effect = in_add_audio_effect;
4015 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4016 in->stream.set_gain = in_set_gain;
4017 in->stream.read = in_read;
4018 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4019
4020 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004021 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023 in->standby = 1;
4024 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004025 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004026 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027
4028 /* Update config params with the requested sample rate and channels */
4029 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004030 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4031 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4032 is_low_latency = true;
4033#if LOW_LATENCY_CAPTURE_USE_CASE
4034 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4035#endif
4036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004039 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304040 in->bit_width = 16;
4041 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004043 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304044 if (adev->mode != AUDIO_MODE_IN_CALL) {
4045 ret = -EINVAL;
4046 goto err_open;
4047 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004048 if (config->sample_rate == 0)
4049 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4050 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4051 config->sample_rate != 8000) {
4052 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4053 ret = -EINVAL;
4054 goto err_open;
4055 }
4056 if (config->format == AUDIO_FORMAT_DEFAULT)
4057 config->format = AUDIO_FORMAT_PCM_16_BIT;
4058 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4059 config->format = AUDIO_FORMAT_PCM_16_BIT;
4060 ret = -EINVAL;
4061 goto err_open;
4062 }
4063
4064 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4065 in->config = pcm_config_afe_proxy_record;
4066 in->config.channels = channel_count;
4067 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304068 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304069 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4070 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004071 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004072 audio_extn_compr_cap_format_supported(config->format) &&
4073 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004074 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004075 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304076 /* restrict 24 bit capture for unprocessed source only
4077 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4078 */
4079 if (config->format == AUDIO_FORMAT_DEFAULT) {
4080 config->format = AUDIO_FORMAT_PCM_16_BIT;
4081 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4082 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4083 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4084 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4085 bool ret_error = false;
4086 in->bit_width = 24;
4087 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4088 from HAL is 24_packed and 8_24
4089 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4090 24_packed return error indicating supported format is 24_packed
4091 *> In case of any other source requesting 24 bit or float return error
4092 indicating format supported is 16 bit only.
4093
4094 on error flinger will retry with supported format passed
4095 */
4096 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4097 (source != AUDIO_SOURCE_CAMCORDER)) {
4098 config->format = AUDIO_FORMAT_PCM_16_BIT;
4099 if( config->sample_rate > 48000)
4100 config->sample_rate = 48000;
4101 ret_error = true;
4102 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4103 in->config.format = PCM_FORMAT_S24_3LE;
4104 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4105 in->config.format = PCM_FORMAT_S24_LE;
4106 } else {
4107 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4108 ret_error = true;
4109 }
4110
4111 if (ret_error) {
4112 ret = -EINVAL;
4113 goto err_open;
4114 }
4115 }
4116
4117 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004118 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004119 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004120 buffer_size = get_input_buffer_size(config->sample_rate,
4121 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004122 channel_count,
4123 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004124 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004125 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4126 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4127 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004128 (in->config.rate == 8000 || in->config.rate == 16000 ||
4129 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004130 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4131 voice_extn_compress_voip_open_input_stream(in);
4132 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004135 /* This stream could be for sound trigger lab,
4136 get sound trigger pcm if present */
4137 audio_extn_sound_trigger_check_and_get_session(in);
4138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004140 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004141 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142
4143err_open:
4144 free(in);
4145 *stream_in = NULL;
4146 return ret;
4147}
4148
4149static void adev_close_input_stream(struct audio_hw_device *dev,
4150 struct audio_stream_in *stream)
4151{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004152 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004153 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004154 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304155
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304156 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004157
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304158 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004159 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304160
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004161 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304162 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004163 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304164 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004165 if (ret != 0)
4166 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4167 __func__, ret);
4168 } else
4169 in_standby(&stream->common);
4170
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004171 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004172 audio_extn_ssr_deinit();
4173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174
Mingming Yine62d7842013-10-25 16:26:03 -07004175 if(audio_extn_compr_cap_enabled() &&
4176 audio_extn_compr_cap_format_supported(in->config.format))
4177 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004178
Mingming Yinfd7607b2016-01-22 12:48:44 -08004179 if (in->is_st_session) {
4180 ALOGV("%s: sound trigger pcm stop lab", __func__);
4181 audio_extn_sound_trigger_stop_lab(in);
4182 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004183 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 return;
4185}
4186
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004187static int adev_dump(const audio_hw_device_t *device __unused,
4188 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189{
4190 return 0;
4191}
4192
4193static int adev_close(hw_device_t *device)
4194{
4195 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004196
4197 if (!adev)
4198 return 0;
4199
4200 pthread_mutex_lock(&adev_init_lock);
4201
4202 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004203 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004204 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004205 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004206 audio_route_free(adev->audio_route);
4207 free(adev->snd_dev_ref_cnt);
4208 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004209 if (adev->adm_deinit)
4210 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004211 free(device);
4212 adev = NULL;
4213 }
4214 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 return 0;
4217}
4218
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004219/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4220 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4221 * just that it _might_ work.
4222 */
4223static int period_size_is_plausible_for_low_latency(int period_size)
4224{
4225 switch (period_size) {
4226 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004227 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004228 case 240:
4229 case 320:
4230 case 480:
4231 return 1;
4232 default:
4233 return 0;
4234 }
4235}
4236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237static int adev_open(const hw_module_t *module, const char *name,
4238 hw_device_t **device)
4239{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004240 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4242
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004243 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004244 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004245 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004246 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004247 ALOGD("%s: returning existing instance of adev", __func__);
4248 ALOGD("%s: exit", __func__);
4249 pthread_mutex_unlock(&adev_init_lock);
4250 return 0;
4251 }
4252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 adev = calloc(1, sizeof(struct audio_device));
4254
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004255 if (!adev) {
4256 pthread_mutex_unlock(&adev_init_lock);
4257 return -ENOMEM;
4258 }
4259
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004260 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4263 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4264 adev->device.common.module = (struct hw_module_t *)module;
4265 adev->device.common.close = adev_close;
4266
4267 adev->device.init_check = adev_init_check;
4268 adev->device.set_voice_volume = adev_set_voice_volume;
4269 adev->device.set_master_volume = adev_set_master_volume;
4270 adev->device.get_master_volume = adev_get_master_volume;
4271 adev->device.set_master_mute = adev_set_master_mute;
4272 adev->device.get_master_mute = adev_get_master_mute;
4273 adev->device.set_mode = adev_set_mode;
4274 adev->device.set_mic_mute = adev_set_mic_mute;
4275 adev->device.get_mic_mute = adev_get_mic_mute;
4276 adev->device.set_parameters = adev_set_parameters;
4277 adev->device.get_parameters = adev_get_parameters;
4278 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4279 adev->device.open_output_stream = adev_open_output_stream;
4280 adev->device.close_output_stream = adev_close_output_stream;
4281 adev->device.open_input_stream = adev_open_input_stream;
4282 adev->device.close_input_stream = adev_close_input_stream;
4283 adev->device.dump = adev_dump;
4284
4285 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004287 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004288 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004291 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004292 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004293 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004294 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004295 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004296 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004297 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004298 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304299 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304300 adev->perf_lock_opts[0] = 0x101;
4301 adev->perf_lock_opts[1] = 0x20E;
4302 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304303
4304 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4305 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004307 adev->platform = platform_init(adev);
4308 if (!adev->platform) {
4309 free(adev->snd_dev_ref_cnt);
4310 free(adev);
4311 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4312 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004313 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004314 return -EINVAL;
4315 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004316
Naresh Tanniru4c630392014-05-12 01:05:52 +05304317 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4318
Eric Laurentc4aef752013-09-12 17:45:53 -07004319 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4320 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4321 if (adev->visualizer_lib == NULL) {
4322 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4323 } else {
4324 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4325 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004326 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004327 "visualizer_hal_start_output");
4328 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004329 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004330 "visualizer_hal_stop_output");
4331 }
4332 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004333 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004334 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004335
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004336 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4337 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4338 if (adev->offload_effects_lib == NULL) {
4339 ALOGE("%s: DLOPEN failed for %s", __func__,
4340 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4341 } else {
4342 ALOGV("%s: DLOPEN successful for %s", __func__,
4343 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4344 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304345 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004346 "offload_effects_bundle_hal_start_output");
4347 adev->offload_effects_stop_output =
4348 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4349 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004350 adev->offload_effects_set_hpx_state =
4351 (int (*)(bool))dlsym(adev->offload_effects_lib,
4352 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304353 adev->offload_effects_get_parameters =
4354 (void (*)(struct str_parms *, struct str_parms *))
4355 dlsym(adev->offload_effects_lib,
4356 "offload_effects_bundle_get_parameters");
4357 adev->offload_effects_set_parameters =
4358 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4359 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004360 }
4361 }
4362
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004363 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4364 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4365 if (adev->adm_lib == NULL) {
4366 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4367 } else {
4368 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4369 adev->adm_init = (adm_init_t)
4370 dlsym(adev->adm_lib, "adm_init");
4371 adev->adm_deinit = (adm_deinit_t)
4372 dlsym(adev->adm_lib, "adm_deinit");
4373 adev->adm_register_input_stream = (adm_register_input_stream_t)
4374 dlsym(adev->adm_lib, "adm_register_input_stream");
4375 adev->adm_register_output_stream = (adm_register_output_stream_t)
4376 dlsym(adev->adm_lib, "adm_register_output_stream");
4377 adev->adm_deregister_stream = (adm_deregister_stream_t)
4378 dlsym(adev->adm_lib, "adm_deregister_stream");
4379 adev->adm_request_focus = (adm_request_focus_t)
4380 dlsym(adev->adm_lib, "adm_request_focus");
4381 adev->adm_abandon_focus = (adm_abandon_focus_t)
4382 dlsym(adev->adm_lib, "adm_abandon_focus");
4383 }
4384 }
4385
Mingming Yin514a8bc2014-07-29 15:22:21 -07004386 adev->bt_wb_speech_enabled = false;
4387
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004388 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389 *device = &adev->device.common;
4390
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004391 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4392 &adev->streams_output_cfg_list);
4393
Kiran Kandi910e1862013-10-29 13:29:42 -07004394 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004395
4396 char value[PROPERTY_VALUE_MAX];
4397 int trial;
4398 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4399 trial = atoi(value);
4400 if (period_size_is_plausible_for_low_latency(trial)) {
4401 pcm_config_low_latency.period_size = trial;
4402 pcm_config_low_latency.start_threshold = trial / 4;
4403 pcm_config_low_latency.avail_min = trial / 4;
4404 configured_low_latency_capture_period_size = trial;
4405 }
4406 }
4407 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4408 trial = atoi(value);
4409 if (period_size_is_plausible_for_low_latency(trial)) {
4410 configured_low_latency_capture_period_size = trial;
4411 }
4412 }
4413
vivek mehta446c3962015-09-14 10:57:35 -07004414 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004415 pthread_mutex_unlock(&adev_init_lock);
4416
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004417 if (adev->adm_init)
4418 adev->adm_data = adev->adm_init();
4419
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304420 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004421 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 return 0;
4423}
4424
4425static struct hw_module_methods_t hal_module_methods = {
4426 .open = adev_open,
4427};
4428
4429struct audio_module HAL_MODULE_INFO_SYM = {
4430 .common = {
4431 .tag = HARDWARE_MODULE_TAG,
4432 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4433 .hal_api_version = HARDWARE_HAL_API_VERSION,
4434 .id = AUDIO_HARDWARE_MODULE_ID,
4435 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004436 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 .methods = &hal_module_methods,
4438 },
4439};