blob: 2a7895c5399443cfeddc46e0da070e39e1b664f4 [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:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302012 case 3:
2013 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002014 case 6:
2015 break;
2016 default:
2017 ret = -EINVAL;
2018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019
2020 switch (sample_rate) {
2021 case 8000:
2022 case 11025:
2023 case 12000:
2024 case 16000:
2025 case 22050:
2026 case 24000:
2027 case 32000:
2028 case 44100:
2029 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302030 case 96000:
2031 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 break;
2033 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002034 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 }
2036
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002037 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038}
2039
2040static size_t get_input_buffer_size(uint32_t sample_rate,
2041 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002042 int channel_count,
2043 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044{
2045 size_t size = 0;
2046
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002047 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2048 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002050 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002051 if (is_low_latency)
2052 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302053
2054 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002056 /* make sure the size is multiple of 32 bytes
2057 * At 48 kHz mono 16-bit PCM:
2058 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2059 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2060 */
2061 size += 0x1f;
2062 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002063
2064 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065}
2066
Ashish Jain5106d362016-05-11 19:23:33 +05302067static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2068{
2069 uint64_t actual_frames_rendered = 0;
2070 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2071
2072 /* This adjustment accounts for buffering after app processor.
2073 * It is based on estimated DSP latency per use case, rather than exact.
2074 */
2075 int64_t platform_latency = platform_render_latency(out->usecase) *
2076 out->sample_rate / 1000000LL;
2077
2078 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2079 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2080 * hence only estimate.
2081 */
2082 int64_t signed_frames = out->written - kernel_buffer_size;
2083
2084 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2085
2086 if (signed_frames > 0)
2087 actual_frames_rendered = signed_frames;
2088
2089 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2090 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2091 (long long int)out->written, (int)kernel_buffer_size,
2092 audio_bytes_per_sample(out->compr_config.codec->format),
2093 popcount(out->channel_mask));
2094
2095 return actual_frames_rendered;
2096}
2097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2099{
2100 struct stream_out *out = (struct stream_out *)stream;
2101
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103}
2104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002105static int out_set_sample_rate(struct audio_stream *stream __unused,
2106 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107{
2108 return -ENOSYS;
2109}
2110
2111static size_t out_get_buffer_size(const struct audio_stream *stream)
2112{
2113 struct stream_out *out = (struct stream_out *)stream;
2114
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002115 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002117 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2118 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002120 return out->config.period_size *
2121 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122}
2123
2124static uint32_t out_get_channels(const struct audio_stream *stream)
2125{
2126 struct stream_out *out = (struct stream_out *)stream;
2127
2128 return out->channel_mask;
2129}
2130
2131static audio_format_t out_get_format(const struct audio_stream *stream)
2132{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 struct stream_out *out = (struct stream_out *)stream;
2134
2135 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136}
2137
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002138static int out_set_format(struct audio_stream *stream __unused,
2139 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140{
2141 return -ENOSYS;
2142}
2143
2144static int out_standby(struct audio_stream *stream)
2145{
2146 struct stream_out *out = (struct stream_out *)stream;
2147 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302149 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2150 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002151 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2152 /* Ignore standby in case of voip call because the voip output
2153 * stream is closed in adev_close_output_stream()
2154 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302155 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002156 return 0;
2157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002159 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002161 if (adev->adm_deregister_stream)
2162 adev->adm_deregister_stream(adev->adm_data, out->handle);
2163
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002164 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002166 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 if (out->pcm) {
2168 pcm_close(out->pcm);
2169 out->pcm = NULL;
2170 }
2171 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002172 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302174 out->send_next_track_params = false;
2175 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002176 out->gapless_mdata.encoder_delay = 0;
2177 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 if (out->compr != NULL) {
2179 compress_close(out->compr);
2180 out->compr = NULL;
2181 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002182 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002184 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 }
2186 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302187 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 return 0;
2189}
2190
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002191static int out_dump(const struct audio_stream *stream __unused,
2192 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193{
2194 return 0;
2195}
2196
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002197static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2198{
2199 int ret = 0;
2200 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002203 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002204 return -EINVAL;
2205 }
2206
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302207 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002208
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002209 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2210 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302211 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002212 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002213 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2214 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302215 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002216 }
2217
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002218 ALOGV("%s new encoder delay %u and padding %u", __func__,
2219 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2220
2221 return 0;
2222}
2223
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002224static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2225{
2226 return out == adev->primary_output || out == adev->voice_tx_output;
2227}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2230{
2231 struct stream_out *out = (struct stream_out *)stream;
2232 struct audio_device *adev = out->dev;
2233 struct str_parms *parms;
2234 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002235 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236
sangwoobc677242013-08-08 16:53:43 +09002237 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302240 if (!parms)
2241 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002242 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2243 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002245 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002246 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002248 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302249 * When HDMI cable is unplugged/usb hs is disconnected the
2250 * music playback is paused and the policy manager sends routing=0
2251 * But the audioflingercontinues to write data until standby time
2252 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 * Avoid this by routing audio to speaker until standby.
2254 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302255 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2256 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 val == AUDIO_DEVICE_NONE) {
Mingming Yin21854652016-04-13 11:54:02 -07002258 if (!audio_extn_dolby_is_passthrough_stream(out))
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002259 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 }
2261
2262 /*
2263 * select_devices() call below switches all the usecases on the same
2264 * backend to the new device. Refer to check_usecases_codec_backend() in
2265 * the select_devices(). But how do we undo this?
2266 *
2267 * For example, music playback is active on headset (deep-buffer usecase)
2268 * and if we go to ringtones and select a ringtone, low-latency usecase
2269 * will be started on headset+speaker. As we can't enable headset+speaker
2270 * and headset devices at the same time, select_devices() switches the music
2271 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2272 * So when the ringtone playback is completed, how do we undo the same?
2273 *
2274 * We are relying on the out_set_parameters() call on deep-buffer output,
2275 * once the ringtone playback is ended.
2276 * NOTE: We should not check if the current devices are same as new devices.
2277 * Because select_devices() must be called to switch back the music
2278 * playback to headset.
2279 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002280 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 out->devices = val;
2282
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302283 if (!out->standby) {
2284 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2285 adev->perf_lock_opts,
2286 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002287 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302288 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2289 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002290
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002291 if (output_drives_call(adev, out)) {
2292 if(!voice_is_in_call(adev)) {
2293 if (adev->mode == AUDIO_MODE_IN_CALL) {
2294 adev->current_call_output = out;
2295 ret = voice_start_call(adev);
2296 }
2297 } else {
2298 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002299 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002300 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002301 }
2302 }
2303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002305 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002307
2308 if (out == adev->primary_output) {
2309 pthread_mutex_lock(&adev->lock);
2310 audio_extn_set_parameters(adev, parms);
2311 pthread_mutex_unlock(&adev->lock);
2312 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002313 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002314 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002315 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002316
2317 audio_extn_dts_create_state_notifier_node(out->usecase);
2318 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2319 popcount(out->channel_mask),
2320 out->playback_started);
2321
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002322 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002323 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302326error:
Eric Laurent994a6932013-07-17 11:51:42 -07002327 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 return ret;
2329}
2330
2331static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2332{
2333 struct stream_out *out = (struct stream_out *)stream;
2334 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002335 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 char value[256];
2337 struct str_parms *reply = str_parms_create();
2338 size_t i, j;
2339 int ret;
2340 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002341
2342 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002343 if (reply) {
2344 str_parms_destroy(reply);
2345 }
2346 if (query) {
2347 str_parms_destroy(query);
2348 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002349 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2350 return NULL;
2351 }
2352
Eric Laurent994a6932013-07-17 11:51:42 -07002353 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2355 if (ret >= 0) {
2356 value[0] = '\0';
2357 i = 0;
2358 while (out->supported_channel_masks[i] != 0) {
2359 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2360 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2361 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002362 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002364 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 first = false;
2366 break;
2367 }
2368 }
2369 i++;
2370 }
2371 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2372 str = str_parms_to_str(reply);
2373 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002374 voice_extn_out_get_parameters(out, query, reply);
2375 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002376 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002377 free(str);
2378 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002379 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002381
Alexy Joseph62142aa2015-11-16 15:10:34 -08002382
2383 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2384 if (ret >= 0) {
2385 value[0] = '\0';
2386 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2387 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302388 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002389 } else {
2390 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302391 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002392 }
2393 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002394 if (str)
2395 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002396 str = str_parms_to_str(reply);
2397 }
2398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002399 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2400 if (ret >= 0) {
2401 value[0] = '\0';
2402 i = 0;
2403 first = true;
2404 while (out->supported_formats[i] != 0) {
2405 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2406 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2407 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002408 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002409 }
2410 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2411 first = false;
2412 break;
2413 }
2414 }
2415 i++;
2416 }
2417 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002418 if (str)
2419 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002420 str = str_parms_to_str(reply);
2421 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002422
2423 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2424 if (ret >= 0) {
2425 value[0] = '\0';
2426 i = 0;
2427 first = true;
2428 while (out->supported_sample_rates[i] != 0) {
2429 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2430 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2431 if (!first) {
2432 strlcat(value, "|", sizeof(value));
2433 }
2434 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2435 first = false;
2436 break;
2437 }
2438 }
2439 i++;
2440 }
2441 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2442 if (str)
2443 free(str);
2444 str = str_parms_to_str(reply);
2445 }
2446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447 str_parms_destroy(query);
2448 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002449 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 return str;
2451}
2452
2453static uint32_t out_get_latency(const struct audio_stream_out *stream)
2454{
2455 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002456 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457
Alexy Josephaa54c872014-12-03 02:46:47 -08002458 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002459 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002460 } else {
2461 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002463 }
2464
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302465 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002466 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467}
2468
2469static int out_set_volume(struct audio_stream_out *stream, float left,
2470 float right)
2471{
Eric Laurenta9024de2013-04-04 09:19:12 -07002472 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 int volume[2];
2474
Eric Laurenta9024de2013-04-04 09:19:12 -07002475 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2476 /* only take left channel into account: the API is for stereo anyway */
2477 out->muted = (left == 0.0f);
2478 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002479 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002480 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002481 /*
2482 * Set mute or umute on HDMI passthrough stream.
2483 * Only take left channel into account.
2484 * Mute is 0 and unmute 1
2485 */
2486 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2487 } else {
2488 char mixer_ctl_name[128];
2489 struct audio_device *adev = out->dev;
2490 struct mixer_ctl *ctl;
2491 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002492 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002494 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2495 "Compress Playback %d Volume", pcm_device_id);
2496 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2497 if (!ctl) {
2498 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2499 __func__, mixer_ctl_name);
2500 return -EINVAL;
2501 }
2502 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2503 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2504 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2505 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002507 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 return -ENOSYS;
2510}
2511
2512static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2513 size_t bytes)
2514{
2515 struct stream_out *out = (struct stream_out *)stream;
2516 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302517 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002518 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002520 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302521
Naresh Tanniru80659832014-06-04 18:17:56 +05302522 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002523
Ashish Jainbbce4322016-02-16 13:25:27 +05302524 if (is_offload_usecase(out->usecase)) {
2525 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302526 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2527 pthread_mutex_unlock(&out->lock);
2528 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302529 } else {
2530 /* increase written size during SSR to avoid mismatch
2531 * with the written frames count in AF
2532 */
2533 out->written += bytes / (out->config.channels * sizeof(short));
2534 ALOGD(" %s: sound card is not active/SSR state", __func__);
2535 ret= -EIO;
2536 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302537 }
2538 }
2539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002541 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002542 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002543 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2544 ret = voice_extn_compress_voip_start_output_stream(out);
2545 else
2546 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002548 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002550 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 goto exit;
2552 }
vivek mehta446c3962015-09-14 10:57:35 -07002553 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002554 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
Ashish Jain81eb2a82015-05-13 10:52:34 +05302557 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002558 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302559 adev->is_channel_status_set = true;
2560 }
2561
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002562 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002563 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002564 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002565 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002566 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2567 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302568 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2569 ALOGD("copl(%p):send next track params in gapless", out);
2570 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2571 out->send_next_track_params = false;
2572 out->is_compr_metadata_avail = false;
2573 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574 }
2575
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302577 if (ret < 0)
2578 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302579 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002580 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302581 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 } else if (-ENETRESET == ret) {
2584 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2585 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2586 pthread_mutex_unlock(&out->lock);
2587 out_standby(&out->stream.common);
2588 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 }
Ashish Jain5106d362016-05-11 19:23:33 +05302590 if ( ret == (ssize_t)bytes && !out->non_blocking)
2591 out->written += bytes;
2592
Naresh Tanniru80659832014-06-04 18:17:56 +05302593 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002595 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 out->playback_started = 1;
2597 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002598
2599 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2600 popcount(out->channel_mask),
2601 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 }
2603 pthread_mutex_unlock(&out->lock);
2604 return ret;
2605 } else {
2606 if (out->pcm) {
2607 if (out->muted)
2608 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002609
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302610 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002611
2612 if (adev->adm_request_focus)
2613 adev->adm_request_focus(adev->adm_data, out->handle);
2614
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002615 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2616 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2617 else
2618 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002619
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302620 if (ret < 0)
2621 ret = -errno;
2622 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002623 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002624
2625 if (adev->adm_abandon_focus)
2626 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
2629
2630exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302631 /* ToDo: There may be a corner case when SSR happens back to back during
2632 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302634 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302635 }
2636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 pthread_mutex_unlock(&out->lock);
2638
2639 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002640 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002641 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302642 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302643 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302644 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302645 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302646 out->standby = true;
2647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302649 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302650 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652 return bytes;
2653}
2654
2655static int out_get_render_position(const struct audio_stream_out *stream,
2656 uint32_t *dsp_frames)
2657{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302659 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002660
2661 if (dsp_frames == NULL)
2662 return -EINVAL;
2663
2664 *dsp_frames = 0;
2665 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002666 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302667
2668 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2669 * this operation and adev_close_output_stream(where out gets reset).
2670 */
2671 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2672 *dsp_frames = get_actual_pcm_frames_rendered(out);
2673 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2674 return 0;
2675 }
2676
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002677 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302678 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302679 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302681 if (ret < 0)
2682 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302684 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002685 }
2686 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302687 if (-ENETRESET == ret) {
2688 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2689 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2690 return -EINVAL;
2691 } else if(ret < 0) {
2692 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2693 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302694 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2695 /*
2696 * Handle corner case where compress session is closed during SSR
2697 * and timestamp is queried
2698 */
2699 ALOGE(" ERROR: sound card not active, return error");
2700 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302701 } else {
2702 return 0;
2703 }
Zhou Song32a556e2015-05-05 10:46:56 +08002704 } else if (audio_is_linear_pcm(out->format)) {
2705 *dsp_frames = out->written;
2706 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 } else
2708 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709}
2710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002711static int out_add_audio_effect(const struct audio_stream *stream __unused,
2712 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713{
2714 return 0;
2715}
2716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002717static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2718 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719{
2720 return 0;
2721}
2722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002723static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2724 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
2726 return -EINVAL;
2727}
2728
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002729static int out_get_presentation_position(const struct audio_stream_out *stream,
2730 uint64_t *frames, struct timespec *timestamp)
2731{
2732 struct stream_out *out = (struct stream_out *)stream;
2733 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002734 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002735
Ashish Jain5106d362016-05-11 19:23:33 +05302736 /* below piece of code is not guarded against any lock because audioFliner serializes
2737 * this operation and adev_close_output_stream( where out gets reset).
2738 */
2739 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2740 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2741 *frames = get_actual_pcm_frames_rendered(out);
2742 /* this is the best we can do */
2743 clock_gettime(CLOCK_MONOTONIC, timestamp);
2744 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2745 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2746 return 0;
2747 }
2748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002749 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002750
Ashish Jain5106d362016-05-11 19:23:33 +05302751 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2752 ret = compress_get_tstamp(out->compr, &dsp_frames,
2753 &out->sample_rate);
2754 ALOGVV("%s rendered frames %ld sample_rate %d",
2755 __func__, dsp_frames, out->sample_rate);
2756 *frames = dsp_frames;
2757 if (ret < 0)
2758 ret = -errno;
2759 if (-ENETRESET == ret) {
2760 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2761 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2762 ret = -EINVAL;
2763 } else
2764 ret = 0;
2765 /* this is the best we can do */
2766 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002767 } else {
2768 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002769 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002770 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2771 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002772 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002773 // This adjustment accounts for buffering after app processor.
2774 // It is based on estimated DSP latency per use case, rather than exact.
2775 signed_frames -=
2776 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2777
Eric Laurent949a0892013-09-20 09:20:13 -07002778 // It would be unusual for this value to be negative, but check just in case ...
2779 if (signed_frames >= 0) {
2780 *frames = signed_frames;
2781 ret = 0;
2782 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002783 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302784 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2785 *frames = out->written;
2786 clock_gettime(CLOCK_MONOTONIC, timestamp);
2787 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002788 }
2789 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002790 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002791 return ret;
2792}
2793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794static int out_set_callback(struct audio_stream_out *stream,
2795 stream_callback_t callback, void *cookie)
2796{
2797 struct stream_out *out = (struct stream_out *)stream;
2798
2799 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002800 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 out->offload_callback = callback;
2802 out->offload_cookie = cookie;
2803 pthread_mutex_unlock(&out->lock);
2804 return 0;
2805}
2806
2807static int out_pause(struct audio_stream_out* stream)
2808{
2809 struct stream_out *out = (struct stream_out *)stream;
2810 int status = -ENOSYS;
2811 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002812 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002813 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002814 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302816 struct audio_device *adev = out->dev;
2817 int snd_scard_state = get_snd_card_state(adev);
2818
2819 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2820 status = compress_pause(out->compr);
2821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002823
Mingming Yin21854652016-04-13 11:54:02 -07002824 if (audio_extn_passthru_is_active()) {
2825 ALOGV("offload use case, pause passthru");
2826 audio_extn_passthru_on_pause(out);
2827 }
2828
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302829 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002830 audio_extn_dts_notify_playback_state(out->usecase, 0,
2831 out->sample_rate, popcount(out->channel_mask),
2832 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 }
2834 pthread_mutex_unlock(&out->lock);
2835 }
2836 return status;
2837}
2838
2839static int out_resume(struct audio_stream_out* stream)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 int status = -ENOSYS;
2843 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002844 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002845 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002847 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302849 struct audio_device *adev = out->dev;
2850 int snd_scard_state = get_snd_card_state(adev);
2851
Mingming Yin21854652016-04-13 11:54:02 -07002852 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2853 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2854 pthread_mutex_lock(&out->dev->lock);
2855 ALOGV("offload resume, check and set hdmi backend again");
2856 check_and_set_hdmi_backend(out);
2857 pthread_mutex_unlock(&out->dev->lock);
2858 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302859 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002860 }
2861 if (!status) {
2862 out->offload_state = OFFLOAD_STATE_PLAYING;
2863 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302864 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002865 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2866 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867 }
2868 pthread_mutex_unlock(&out->lock);
2869 }
2870 return status;
2871}
2872
2873static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876 int status = -ENOSYS;
2877 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002878 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002879 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2881 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2882 else
2883 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2884 pthread_mutex_unlock(&out->lock);
2885 }
2886 return status;
2887}
2888
2889static int out_flush(struct audio_stream_out* stream)
2890{
2891 struct stream_out *out = (struct stream_out *)stream;
2892 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002893 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002894 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002895 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302897 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002899 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 return 0;
2901 }
2902 return -ENOSYS;
2903}
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905/** audio_stream_in implementation **/
2906static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2907{
2908 struct stream_in *in = (struct stream_in *)stream;
2909
2910 return in->config.rate;
2911}
2912
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002913static int in_set_sample_rate(struct audio_stream *stream __unused,
2914 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915{
2916 return -ENOSYS;
2917}
2918
2919static size_t in_get_buffer_size(const struct audio_stream *stream)
2920{
2921 struct stream_in *in = (struct stream_in *)stream;
2922
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002923 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2924 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002925 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2926 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002927
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002928 return in->config.period_size *
2929 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930}
2931
2932static uint32_t in_get_channels(const struct audio_stream *stream)
2933{
2934 struct stream_in *in = (struct stream_in *)stream;
2935
2936 return in->channel_mask;
2937}
2938
2939static audio_format_t in_get_format(const struct audio_stream *stream)
2940{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002941 struct stream_in *in = (struct stream_in *)stream;
2942
2943 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944}
2945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002946static int in_set_format(struct audio_stream *stream __unused,
2947 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948{
2949 return -ENOSYS;
2950}
2951
2952static int in_standby(struct audio_stream *stream)
2953{
2954 struct stream_in *in = (struct stream_in *)stream;
2955 struct audio_device *adev = in->dev;
2956 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302957 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2958 stream, in->usecase, use_case_table[in->usecase]);
2959
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002960 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2961 /* Ignore standby in case of voip call because the voip input
2962 * stream is closed in adev_close_input_stream()
2963 */
2964 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2965 return status;
2966 }
2967
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002968 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002969 if (!in->standby && in->is_st_session) {
2970 ALOGD("%s: sound trigger pcm stop lab", __func__);
2971 audio_extn_sound_trigger_stop_lab(in);
2972 in->standby = 1;
2973 }
2974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002976 if (adev->adm_deregister_stream)
2977 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2978
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002979 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002981 if (in->pcm) {
2982 pcm_close(in->pcm);
2983 in->pcm = NULL;
2984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002986 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 }
2988 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002989 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 return status;
2991}
2992
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002993static int in_dump(const struct audio_stream *stream __unused,
2994 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995{
2996 return 0;
2997}
2998
2999static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3000{
3001 struct stream_in *in = (struct stream_in *)stream;
3002 struct audio_device *adev = in->dev;
3003 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003005 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303007 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 parms = str_parms_create_str(kvpairs);
3009
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303010 if (!parms)
3011 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003012 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003013 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003014
3015 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3016 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 val = atoi(value);
3018 /* no audio source uses val == 0 */
3019 if ((in->source != val) && (val != 0)) {
3020 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003021 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3022 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3023 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003024 (in->config.rate == 8000 || in->config.rate == 16000 ||
3025 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003026 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003027 err = voice_extn_compress_voip_open_input_stream(in);
3028 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003029 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003030 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003031 }
3032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 }
3034 }
3035
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003036 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3037 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003039 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 in->device = val;
3041 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003042 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003043 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 }
3045 }
3046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003048 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
3050 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303051error:
Eric Laurent994a6932013-07-17 11:51:42 -07003052 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 return ret;
3054}
3055
3056static char* in_get_parameters(const struct audio_stream *stream,
3057 const char *keys)
3058{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003059 struct stream_in *in = (struct stream_in *)stream;
3060 struct str_parms *query = str_parms_create_str(keys);
3061 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003062 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003063
3064 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003065 if (reply) {
3066 str_parms_destroy(reply);
3067 }
3068 if (query) {
3069 str_parms_destroy(query);
3070 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003071 ALOGE("in_get_parameters: failed to create query or reply");
3072 return NULL;
3073 }
3074
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 ALOGV("%s: enter: keys - %s", __func__, keys);
3076
3077 voice_extn_in_get_parameters(in, query, reply);
3078
3079 str = str_parms_to_str(reply);
3080 str_parms_destroy(query);
3081 str_parms_destroy(reply);
3082
3083 ALOGV("%s: exit: returns - %s", __func__, str);
3084 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085}
3086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003087static int in_set_gain(struct audio_stream_in *stream __unused,
3088 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089{
3090 return 0;
3091}
3092
3093static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3094 size_t bytes)
3095{
3096 struct stream_in *in = (struct stream_in *)stream;
3097 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303098 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303099 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303100 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003102 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303103
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003104 if (in->is_st_session) {
3105 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3106 /* Read from sound trigger HAL */
3107 audio_extn_sound_trigger_read(in, buffer, bytes);
3108 pthread_mutex_unlock(&in->lock);
3109 return bytes;
3110 }
3111
Ashish Jainbbce4322016-02-16 13:25:27 +05303112 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003113 ALOGD(" %s: sound card is not active/SSR state", __func__);
3114 ret= -EIO;;
3115 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303116 }
3117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003119 pthread_mutex_lock(&adev->lock);
3120 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3121 ret = voice_extn_compress_voip_start_input_stream(in);
3122 else
3123 ret = start_input_stream(in);
3124 pthread_mutex_unlock(&adev->lock);
3125 if (ret != 0) {
3126 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 }
3128 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003129 if (adev->adm_register_input_stream)
3130 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003133 if (adev->adm_request_focus)
3134 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303137 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003138 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303139 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003140 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303141 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003142 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303143 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003144 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303145 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3146 if (bytes % 4 == 0) {
3147 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3148 int_buf_stream = buffer;
3149 for (size_t itt=0; itt < bytes/4 ; itt++) {
3150 int_buf_stream[itt] >>= 8;
3151 }
3152 } else {
3153 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3154 ret = -EINVAL;
3155 goto exit;
3156 }
3157 } if (ret < 0) {
3158 ret = -errno;
3159 }
3160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003163 if (adev->adm_abandon_focus)
3164 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 /*
3167 * Instead of writing zeroes here, we could trust the hardware
3168 * to always provide zeroes when muted.
3169 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303170 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3171 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 memset(buffer, 0, bytes);
3173
3174exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303175 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303176 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003177 if (-ENETRESET == ret)
3178 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 pthread_mutex_unlock(&in->lock);
3181
3182 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303183 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303184 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303185 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303186 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303187 in->standby = true;
3188 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303189 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003191 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303192 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303193 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 }
3195 return bytes;
3196}
3197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003198static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199{
3200 return 0;
3201}
3202
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003203static int add_remove_audio_effect(const struct audio_stream *stream,
3204 effect_handle_t effect,
3205 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003207 struct stream_in *in = (struct stream_in *)stream;
3208 int status = 0;
3209 effect_descriptor_t desc;
3210
3211 status = (*effect)->get_descriptor(effect, &desc);
3212 if (status != 0)
3213 return status;
3214
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003215 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003216 pthread_mutex_lock(&in->dev->lock);
3217 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3218 in->enable_aec != enable &&
3219 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3220 in->enable_aec = enable;
3221 if (!in->standby)
3222 select_devices(in->dev, in->usecase);
3223 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003224 if (in->enable_ns != enable &&
3225 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3226 in->enable_ns = enable;
3227 if (!in->standby)
3228 select_devices(in->dev, in->usecase);
3229 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003230 pthread_mutex_unlock(&in->dev->lock);
3231 pthread_mutex_unlock(&in->lock);
3232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 return 0;
3234}
3235
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003236static int in_add_audio_effect(const struct audio_stream *stream,
3237 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238{
Eric Laurent994a6932013-07-17 11:51:42 -07003239 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003240 return add_remove_audio_effect(stream, effect, true);
3241}
3242
3243static int in_remove_audio_effect(const struct audio_stream *stream,
3244 effect_handle_t effect)
3245{
Eric Laurent994a6932013-07-17 11:51:42 -07003246 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003247 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
3250static int adev_open_output_stream(struct audio_hw_device *dev,
3251 audio_io_handle_t handle,
3252 audio_devices_t devices,
3253 audio_output_flags_t flags,
3254 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003255 struct audio_stream_out **stream_out,
3256 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 struct audio_device *adev = (struct audio_device *)dev;
3259 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303260 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003261 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303264
3265 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3266 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003267 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303268 return -EINVAL;
3269 }
3270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3272
Mingming Yin3a941d42016-02-17 18:08:05 -08003273 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3274 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303275 devices, flags, &out->stream);
3276
3277
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003278 if (!out) {
3279 return -ENOMEM;
3280 }
3281
Haynes Mathew George204045b2015-02-25 20:32:03 -08003282 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003283 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003284 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 if (devices == AUDIO_DEVICE_NONE)
3287 devices = AUDIO_DEVICE_OUT_SPEAKER;
3288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 out->flags = flags;
3290 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003291 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003292 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 out->sample_rate = config->sample_rate;
3294 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3295 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003296 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003297 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003298 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299
Mingming Yin3a941d42016-02-17 18:08:05 -08003300 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3301 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3302 pthread_mutex_lock(&adev->lock);
3303 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3304 ret = read_hdmi_sink_caps(out);
3305 pthread_mutex_unlock(&adev->lock);
3306 if (ret != 0) {
3307 if (ret == -ENOSYS) {
3308 /* ignore and go with default */
3309 ret = 0;
3310 } else {
3311 ALOGE("error reading hdmi sink caps");
3312 goto error_open;
3313 }
3314 }
3315 }
3316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003318 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303319 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3320 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003321 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3322 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3323
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003324 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003325 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3326 /*
3327 * Do not handle stereo output in Multi-channel cases
3328 * Stereo case is handled in normal playback path
3329 */
3330 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3331 ret = AUDIO_CHANNEL_OUT_STEREO;
3332 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003333
3334 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3335 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003336 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003337 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003338 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003339
3340 if (config->sample_rate == 0)
3341 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3342 if (config->channel_mask == 0)
3343 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003344 if (config->format == 0)
3345 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003346
3347 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003349 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3351 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003353 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003355 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3356 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003357 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003358 ret = voice_extn_compress_voip_open_output_stream(out);
3359 if (ret != 0) {
3360 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3361 __func__, ret);
3362 goto error_open;
3363 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003364 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3365 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3368 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3369 ALOGE("%s: Unsupported Offload information", __func__);
3370 ret = -EINVAL;
3371 goto error_open;
3372 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003373
Mingming Yin3a941d42016-02-17 18:08:05 -08003374 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003375 if(config->offload_info.format == 0)
3376 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003377 if (config->offload_info.sample_rate == 0)
3378 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003379 }
3380
Mingming Yin90310102013-11-13 16:57:00 -08003381 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003382 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003383 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 ret = -EINVAL;
3385 goto error_open;
3386 }
3387
3388 out->compr_config.codec = (struct snd_codec *)
3389 calloc(1, sizeof(struct snd_codec));
3390
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003391 if (!out->compr_config.codec) {
3392 ret = -ENOMEM;
3393 goto error_open;
3394 }
3395
vivek mehta0ea887a2015-08-26 14:01:20 -07003396 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303397 out->stream.pause = out_pause;
3398 out->stream.flush = out_flush;
3399 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003400 out->usecase = get_offload_usecase(adev, true);
3401 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003402 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003403 out->stream.set_callback = out_set_callback;
3404 out->stream.pause = out_pause;
3405 out->stream.resume = out_resume;
3406 out->stream.drain = out_drain;
3407 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003408 out->usecase = get_offload_usecase(adev, false);
3409 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003410 }
vivek mehta446c3962015-09-14 10:57:35 -07003411
3412 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003413 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3414 config->format == 0 && config->sample_rate == 0 &&
3415 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003416 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003417 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3418 } else {
3419 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3420 ret = -EEXIST;
3421 goto error_open;
3422 }
vivek mehta446c3962015-09-14 10:57:35 -07003423 }
3424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 if (config->offload_info.channel_mask)
3426 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003427 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003428 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003429 config->offload_info.channel_mask = config->channel_mask;
3430 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003431 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 out->sample_rate = config->offload_info.sample_rate;
3433
Mingming Yin3ee55c62014-08-04 14:23:35 -07003434 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003436 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003437 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003438 audio_extn_dolby_get_snd_codec_id(adev, out,
3439 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003440 else
3441 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003443
Ashish Jain5106d362016-05-11 19:23:33 +05303444 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003445 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003446 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303447 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Mingming Yin21854652016-04-13 11:54:02 -07003448 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003449 out->compr_config.fragment_size =
3450 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303451 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003452 } else {
3453 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003454 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303455 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003456 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003458 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 out->compr_config.codec->bit_rate =
3460 config->offload_info.bit_rate;
3461 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003462 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303464 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003465 /*TODO: Do we need to change it for passthrough */
3466 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467
Manish Dewangana6fc5442015-08-24 20:30:31 +05303468 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3469 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3470 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3471 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003472 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3473 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303474 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3475 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3476 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003477 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003478
Amit Shekhar6f461b12014-08-01 14:52:58 -07003479 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303480 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3483 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003484
Alexy Josephaa54c872014-12-03 02:46:47 -08003485
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003486 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303487 out->send_next_track_params = false;
3488 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003489 out->offload_state = OFFLOAD_STATE_IDLE;
3490 out->playback_started = 0;
3491
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003492 audio_extn_dts_create_state_notifier_node(out->usecase);
3493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494 create_offload_callback_thread(out);
3495 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3496 __func__, config->offload_info.version,
3497 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303498
3499 /* Disable gapless if any of the following is true
3500 * passthrough playback
3501 * AV playback
3502 * Direct PCM playback
3503 */
3504 if (audio_extn_dolby_is_passthrough_stream(out) ||
3505 config->offload_info.has_video ||
3506 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3507 check_and_set_gapless_mode(adev, false);
3508 } else
3509 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003510
3511 if (audio_extn_dolby_is_passthrough_stream(out)) {
3512 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3513 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003514 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303515 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003516 if (ret != 0) {
3517 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3518 __func__, ret);
3519 goto error_open;
3520 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3522 if (config->sample_rate == 0)
3523 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3524 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3525 config->sample_rate != 8000) {
3526 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3527 ret = -EINVAL;
3528 goto error_open;
3529 }
3530 out->sample_rate = config->sample_rate;
3531 out->config.rate = config->sample_rate;
3532 if (config->format == AUDIO_FORMAT_DEFAULT)
3533 config->format = AUDIO_FORMAT_PCM_16_BIT;
3534 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3535 config->format = AUDIO_FORMAT_PCM_16_BIT;
3536 ret = -EINVAL;
3537 goto error_open;
3538 }
3539 out->format = config->format;
3540 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3541 out->config = pcm_config_afe_proxy_playback;
3542 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003543 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3544 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3545 out->config = pcm_config_low_latency;
3546 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003547 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003548 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3550 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003552 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3553 format = AUDIO_FORMAT_PCM_16_BIT;
3554 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3555 out->config = pcm_config_deep_buffer;
3556 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003557 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003558 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003559 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003560 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003561 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003562 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 }
3564
Mingming Yin21854652016-04-13 11:54:02 -07003565 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3566 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003567 /* TODO remove this hardcoding and check why width is zero*/
3568 if (out->bit_width == 0)
3569 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003570 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3571 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003572 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303573 out->bit_width, out->channel_mask,
3574 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003575 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3576 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3577 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003578 if(adev->primary_output == NULL)
3579 adev->primary_output = out;
3580 else {
3581 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003582 ret = -EEXIST;
3583 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003584 }
3585 }
3586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 /* Check if this usecase is already existing */
3588 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003589 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3590 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003593 ret = -EEXIST;
3594 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 }
3596 pthread_mutex_unlock(&adev->lock);
3597
3598 out->stream.common.get_sample_rate = out_get_sample_rate;
3599 out->stream.common.set_sample_rate = out_set_sample_rate;
3600 out->stream.common.get_buffer_size = out_get_buffer_size;
3601 out->stream.common.get_channels = out_get_channels;
3602 out->stream.common.get_format = out_get_format;
3603 out->stream.common.set_format = out_set_format;
3604 out->stream.common.standby = out_standby;
3605 out->stream.common.dump = out_dump;
3606 out->stream.common.set_parameters = out_set_parameters;
3607 out->stream.common.get_parameters = out_get_parameters;
3608 out->stream.common.add_audio_effect = out_add_audio_effect;
3609 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3610 out->stream.get_latency = out_get_latency;
3611 out->stream.set_volume = out_set_volume;
3612 out->stream.write = out_write;
3613 out->stream.get_render_position = out_get_render_position;
3614 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003615 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003618 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003619 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
3621 config->format = out->stream.common.get_format(&out->stream.common);
3622 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3623 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3624
3625 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303626 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003627 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003628
3629 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3630 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3631 popcount(out->channel_mask), out->playback_started);
3632
Eric Laurent994a6932013-07-17 11:51:42 -07003633 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003635
3636error_open:
3637 free(out);
3638 *stream_out = NULL;
3639 ALOGD("%s: exit: ret %d", __func__, ret);
3640 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003643static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 struct audio_stream_out *stream)
3645{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003646 struct stream_out *out = (struct stream_out *)stream;
3647 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003648 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003649
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303650 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3651
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003652 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303653 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003654 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303655 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003656 if(ret != 0)
3657 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3658 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003660 out_standby(&stream->common);
3661
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003662 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003663 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003665 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 if (out->compr_config.codec != NULL)
3667 free(out->compr_config.codec);
3668 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003669
3670 if (adev->voice_tx_output == out)
3671 adev->voice_tx_output = NULL;
3672
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 pthread_cond_destroy(&out->cond);
3674 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003676 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677}
3678
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003679static void close_compress_sessions(struct audio_device *adev)
3680{
Mingming Yin7b762e72015-03-04 13:47:32 -08003681 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303682 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003683 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003684 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303685
3686 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003687 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303688 if (is_offload_usecase(usecase->id)) {
3689 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003690 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3691 out = usecase->stream.out;
3692 pthread_mutex_unlock(&adev->lock);
3693 out_standby(&out->stream.common);
3694 pthread_mutex_lock(&adev->lock);
3695 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303696 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003697 }
3698 pthread_mutex_unlock(&adev->lock);
3699}
3700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3702{
3703 struct audio_device *adev = (struct audio_device *)dev;
3704 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003706 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003707 int ret;
3708 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003710 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303713 if (!parms)
3714 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003715 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3716 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303717 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718 if (strstr(snd_card_status, "OFFLINE")) {
3719 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303720 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003721 //close compress sessions on OFFLINE status
3722 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303723 } else if (strstr(snd_card_status, "ONLINE")) {
3724 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303725 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003726 //send dts hpx license if enabled
3727 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303728 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303729 }
3730
3731 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003732 status = voice_set_parameters(adev, parms);
3733 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003734 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003736 status = platform_set_parameters(adev->platform, parms);
3737 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003738 goto done;
3739
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003740 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3741 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003742 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3744 adev->bluetooth_nrec = true;
3745 else
3746 adev->bluetooth_nrec = false;
3747 }
3748
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003749 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3750 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3752 adev->screen_off = false;
3753 else
3754 adev->screen_off = true;
3755 }
3756
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003757 ret = str_parms_get_int(parms, "rotation", &val);
3758 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003759 bool reverse_speakers = false;
3760 switch(val) {
3761 // FIXME: note that the code below assumes that the speakers are in the correct placement
3762 // relative to the user when the device is rotated 90deg from its default rotation. This
3763 // assumption is device-specific, not platform-specific like this code.
3764 case 270:
3765 reverse_speakers = true;
3766 break;
3767 case 0:
3768 case 90:
3769 case 180:
3770 break;
3771 default:
3772 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003773 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003774 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003775 if (status == 0) {
3776 if (adev->speaker_lr_swap != reverse_speakers) {
3777 adev->speaker_lr_swap = reverse_speakers;
3778 // only update the selected device if there is active pcm playback
3779 struct audio_usecase *usecase;
3780 struct listnode *node;
3781 list_for_each(node, &adev->usecase_list) {
3782 usecase = node_to_item(node, struct audio_usecase, list);
3783 if (usecase->type == PCM_PLAYBACK) {
3784 select_devices(adev, usecase->id);
3785 break;
3786 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003787 }
3788 }
3789 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003790 }
3791
Mingming Yin514a8bc2014-07-29 15:22:21 -07003792 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3793 if (ret >= 0) {
3794 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3795 adev->bt_wb_speech_enabled = true;
3796 else
3797 adev->bt_wb_speech_enabled = false;
3798 }
3799
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003800 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3801 if (ret >= 0) {
3802 val = atoi(value);
3803 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3804 ALOGV("cache new edid");
3805 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003806 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3807 /*
3808 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3809 * Per AudioPolicyManager, USB device is higher priority than WFD.
3810 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3811 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3812 * starting voice call on USB
3813 */
3814 ALOGV("detected USB connect .. disable proxy");
3815 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003816 }
3817 }
3818
3819 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3820 if (ret >= 0) {
3821 val = atoi(value);
3822 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3823 ALOGV("invalidate cached edid");
3824 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003825 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3826 ALOGV("detected USB disconnect .. enable proxy");
3827 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003828 }
3829 }
3830
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003831 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003832
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003833done:
3834 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003835 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303836error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003837 ALOGV("%s: exit with code(%d)", __func__, status);
3838 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839}
3840
3841static char* adev_get_parameters(const struct audio_hw_device *dev,
3842 const char *keys)
3843{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003844 struct audio_device *adev = (struct audio_device *)dev;
3845 struct str_parms *reply = str_parms_create();
3846 struct str_parms *query = str_parms_create_str(keys);
3847 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303848 char value[256] = {0};
3849 int ret = 0;
3850
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003851 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003852 if (reply) {
3853 str_parms_destroy(reply);
3854 }
3855 if (query) {
3856 str_parms_destroy(query);
3857 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003858 ALOGE("adev_get_parameters: failed to create query or reply");
3859 return NULL;
3860 }
3861
Naresh Tannirud7205b62014-06-20 02:54:48 +05303862 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3863 sizeof(value));
3864 if (ret >=0) {
3865 int val = 1;
3866 pthread_mutex_lock(&adev->snd_card_status.lock);
3867 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3868 val = 0;
3869 pthread_mutex_unlock(&adev->snd_card_status.lock);
3870 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3871 goto exit;
3872 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003873
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003874 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003875 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003876 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003877 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303878 pthread_mutex_unlock(&adev->lock);
3879
Naresh Tannirud7205b62014-06-20 02:54:48 +05303880exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003881 str = str_parms_to_str(reply);
3882 str_parms_destroy(query);
3883 str_parms_destroy(reply);
3884
3885 ALOGV("%s: exit: returns - %s", __func__, str);
3886 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887}
3888
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003889static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890{
3891 return 0;
3892}
3893
3894static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3895{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003896 int ret;
3897 struct audio_device *adev = (struct audio_device *)dev;
3898 pthread_mutex_lock(&adev->lock);
3899 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003900 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003901 pthread_mutex_unlock(&adev->lock);
3902 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903}
3904
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003905static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3906 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907{
3908 return -ENOSYS;
3909}
3910
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003911static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3912 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913{
3914 return -ENOSYS;
3915}
3916
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003917static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3918 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919{
3920 return -ENOSYS;
3921}
3922
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003923static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3924 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925{
3926 return -ENOSYS;
3927}
3928
3929static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3930{
3931 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 pthread_mutex_lock(&adev->lock);
3934 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003935 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003937 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003938 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003939 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003940 adev->current_call_output = NULL;
3941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 }
3943 pthread_mutex_unlock(&adev->lock);
3944 return 0;
3945}
3946
3947static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3948{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003949 int ret;
3950
3951 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003952 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003953 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3954 pthread_mutex_unlock(&adev->lock);
3955
3956 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957}
3958
3959static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3960{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003961 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 return 0;
3963}
3964
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003965static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 const struct audio_config *config)
3967{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003968 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003970 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3971 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972}
3973
3974static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003975 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 audio_devices_t devices,
3977 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003978 struct audio_stream_in **stream_in,
3979 audio_input_flags_t flags __unused,
3980 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003981 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982{
3983 struct audio_device *adev = (struct audio_device *)dev;
3984 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003985 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003986 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003987 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303990 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
3991 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303993 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994
3995 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003996
3997 if (!in) {
3998 ALOGE("failed to allocate input stream");
3999 return -ENOMEM;
4000 }
4001
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304002 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304003 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4004 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004005 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004006 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 in->stream.common.get_sample_rate = in_get_sample_rate;
4009 in->stream.common.set_sample_rate = in_set_sample_rate;
4010 in->stream.common.get_buffer_size = in_get_buffer_size;
4011 in->stream.common.get_channels = in_get_channels;
4012 in->stream.common.get_format = in_get_format;
4013 in->stream.common.set_format = in_set_format;
4014 in->stream.common.standby = in_standby;
4015 in->stream.common.dump = in_dump;
4016 in->stream.common.set_parameters = in_set_parameters;
4017 in->stream.common.get_parameters = in_get_parameters;
4018 in->stream.common.add_audio_effect = in_add_audio_effect;
4019 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4020 in->stream.set_gain = in_set_gain;
4021 in->stream.read = in_read;
4022 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4023
4024 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004025 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027 in->standby = 1;
4028 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004029 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004030 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031
4032 /* Update config params with the requested sample rate and channels */
4033 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004034 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4035 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4036 is_low_latency = true;
4037#if LOW_LATENCY_CAPTURE_USE_CASE
4038 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4039#endif
4040 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004043 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304044 in->bit_width = 16;
4045 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004047 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304048 if (adev->mode != AUDIO_MODE_IN_CALL) {
4049 ret = -EINVAL;
4050 goto err_open;
4051 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004052 if (config->sample_rate == 0)
4053 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4054 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4055 config->sample_rate != 8000) {
4056 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4057 ret = -EINVAL;
4058 goto err_open;
4059 }
4060 if (config->format == AUDIO_FORMAT_DEFAULT)
4061 config->format = AUDIO_FORMAT_PCM_16_BIT;
4062 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4063 config->format = AUDIO_FORMAT_PCM_16_BIT;
4064 ret = -EINVAL;
4065 goto err_open;
4066 }
4067
4068 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4069 in->config = pcm_config_afe_proxy_record;
4070 in->config.channels = channel_count;
4071 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304072 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304073 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4074 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004075 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004076 audio_extn_compr_cap_format_supported(config->format) &&
4077 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004078 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004079 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304080 /* restrict 24 bit capture for unprocessed source only
4081 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4082 */
4083 if (config->format == AUDIO_FORMAT_DEFAULT) {
4084 config->format = AUDIO_FORMAT_PCM_16_BIT;
4085 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4086 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4087 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4088 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4089 bool ret_error = false;
4090 in->bit_width = 24;
4091 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4092 from HAL is 24_packed and 8_24
4093 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4094 24_packed return error indicating supported format is 24_packed
4095 *> In case of any other source requesting 24 bit or float return error
4096 indicating format supported is 16 bit only.
4097
4098 on error flinger will retry with supported format passed
4099 */
4100 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4101 (source != AUDIO_SOURCE_CAMCORDER)) {
4102 config->format = AUDIO_FORMAT_PCM_16_BIT;
4103 if( config->sample_rate > 48000)
4104 config->sample_rate = 48000;
4105 ret_error = true;
4106 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4107 in->config.format = PCM_FORMAT_S24_3LE;
4108 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4109 in->config.format = PCM_FORMAT_S24_LE;
4110 } else {
4111 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4112 ret_error = true;
4113 }
4114
4115 if (ret_error) {
4116 ret = -EINVAL;
4117 goto err_open;
4118 }
4119 }
4120
4121 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004122 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004123 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004124 buffer_size = get_input_buffer_size(config->sample_rate,
4125 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004126 channel_count,
4127 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004128 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004129 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4130 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4131 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004132 (in->config.rate == 8000 || in->config.rate == 16000 ||
4133 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004134 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4135 voice_extn_compress_voip_open_input_stream(in);
4136 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004139 /* This stream could be for sound trigger lab,
4140 get sound trigger pcm if present */
4141 audio_extn_sound_trigger_check_and_get_session(in);
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004144 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146
4147err_open:
4148 free(in);
4149 *stream_in = NULL;
4150 return ret;
4151}
4152
4153static void adev_close_input_stream(struct audio_hw_device *dev,
4154 struct audio_stream_in *stream)
4155{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004156 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004157 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004158 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304159
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304160 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004161
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304162 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004163 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304164
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004165 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304166 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004167 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304168 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004169 if (ret != 0)
4170 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4171 __func__, ret);
4172 } else
4173 in_standby(&stream->common);
4174
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004175 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004176 audio_extn_ssr_deinit();
4177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178
Mingming Yine62d7842013-10-25 16:26:03 -07004179 if(audio_extn_compr_cap_enabled() &&
4180 audio_extn_compr_cap_format_supported(in->config.format))
4181 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004182
Mingming Yinfd7607b2016-01-22 12:48:44 -08004183 if (in->is_st_session) {
4184 ALOGV("%s: sound trigger pcm stop lab", __func__);
4185 audio_extn_sound_trigger_stop_lab(in);
4186 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004187 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 return;
4189}
4190
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004191static int adev_dump(const audio_hw_device_t *device __unused,
4192 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193{
4194 return 0;
4195}
4196
4197static int adev_close(hw_device_t *device)
4198{
4199 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004200
4201 if (!adev)
4202 return 0;
4203
4204 pthread_mutex_lock(&adev_init_lock);
4205
4206 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004207 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004208 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004209 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004210 audio_route_free(adev->audio_route);
4211 free(adev->snd_dev_ref_cnt);
4212 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004213 if (adev->adm_deinit)
4214 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004215 free(device);
4216 adev = NULL;
4217 }
4218 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 return 0;
4221}
4222
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004223/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4224 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4225 * just that it _might_ work.
4226 */
4227static int period_size_is_plausible_for_low_latency(int period_size)
4228{
4229 switch (period_size) {
4230 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004231 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004232 case 240:
4233 case 320:
4234 case 480:
4235 return 1;
4236 default:
4237 return 0;
4238 }
4239}
4240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241static int adev_open(const hw_module_t *module, const char *name,
4242 hw_device_t **device)
4243{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004244 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4246
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004247 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004248 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004249 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004250 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004251 ALOGD("%s: returning existing instance of adev", __func__);
4252 ALOGD("%s: exit", __func__);
4253 pthread_mutex_unlock(&adev_init_lock);
4254 return 0;
4255 }
4256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257 adev = calloc(1, sizeof(struct audio_device));
4258
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004259 if (!adev) {
4260 pthread_mutex_unlock(&adev_init_lock);
4261 return -ENOMEM;
4262 }
4263
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004264 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4267 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4268 adev->device.common.module = (struct hw_module_t *)module;
4269 adev->device.common.close = adev_close;
4270
4271 adev->device.init_check = adev_init_check;
4272 adev->device.set_voice_volume = adev_set_voice_volume;
4273 adev->device.set_master_volume = adev_set_master_volume;
4274 adev->device.get_master_volume = adev_get_master_volume;
4275 adev->device.set_master_mute = adev_set_master_mute;
4276 adev->device.get_master_mute = adev_get_master_mute;
4277 adev->device.set_mode = adev_set_mode;
4278 adev->device.set_mic_mute = adev_set_mic_mute;
4279 adev->device.get_mic_mute = adev_get_mic_mute;
4280 adev->device.set_parameters = adev_set_parameters;
4281 adev->device.get_parameters = adev_get_parameters;
4282 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4283 adev->device.open_output_stream = adev_open_output_stream;
4284 adev->device.close_output_stream = adev_close_output_stream;
4285 adev->device.open_input_stream = adev_open_input_stream;
4286 adev->device.close_input_stream = adev_close_input_stream;
4287 adev->device.dump = adev_dump;
4288
4289 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004291 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004292 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004295 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004296 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004297 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004298 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004299 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004300 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004301 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004302 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304303 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304304 adev->perf_lock_opts[0] = 0x101;
4305 adev->perf_lock_opts[1] = 0x20E;
4306 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304307
4308 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4309 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004311 adev->platform = platform_init(adev);
4312 if (!adev->platform) {
4313 free(adev->snd_dev_ref_cnt);
4314 free(adev);
4315 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4316 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004317 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004318 return -EINVAL;
4319 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004320
Naresh Tanniru4c630392014-05-12 01:05:52 +05304321 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4322
Eric Laurentc4aef752013-09-12 17:45:53 -07004323 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4324 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4325 if (adev->visualizer_lib == NULL) {
4326 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4327 } else {
4328 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4329 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004330 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004331 "visualizer_hal_start_output");
4332 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004333 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004334 "visualizer_hal_stop_output");
4335 }
4336 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004337 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004338 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004339
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004340 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4341 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4342 if (adev->offload_effects_lib == NULL) {
4343 ALOGE("%s: DLOPEN failed for %s", __func__,
4344 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4345 } else {
4346 ALOGV("%s: DLOPEN successful for %s", __func__,
4347 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4348 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304349 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004350 "offload_effects_bundle_hal_start_output");
4351 adev->offload_effects_stop_output =
4352 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4353 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004354 adev->offload_effects_set_hpx_state =
4355 (int (*)(bool))dlsym(adev->offload_effects_lib,
4356 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304357 adev->offload_effects_get_parameters =
4358 (void (*)(struct str_parms *, struct str_parms *))
4359 dlsym(adev->offload_effects_lib,
4360 "offload_effects_bundle_get_parameters");
4361 adev->offload_effects_set_parameters =
4362 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4363 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004364 }
4365 }
4366
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004367 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4368 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4369 if (adev->adm_lib == NULL) {
4370 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4371 } else {
4372 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4373 adev->adm_init = (adm_init_t)
4374 dlsym(adev->adm_lib, "adm_init");
4375 adev->adm_deinit = (adm_deinit_t)
4376 dlsym(adev->adm_lib, "adm_deinit");
4377 adev->adm_register_input_stream = (adm_register_input_stream_t)
4378 dlsym(adev->adm_lib, "adm_register_input_stream");
4379 adev->adm_register_output_stream = (adm_register_output_stream_t)
4380 dlsym(adev->adm_lib, "adm_register_output_stream");
4381 adev->adm_deregister_stream = (adm_deregister_stream_t)
4382 dlsym(adev->adm_lib, "adm_deregister_stream");
4383 adev->adm_request_focus = (adm_request_focus_t)
4384 dlsym(adev->adm_lib, "adm_request_focus");
4385 adev->adm_abandon_focus = (adm_abandon_focus_t)
4386 dlsym(adev->adm_lib, "adm_abandon_focus");
4387 }
4388 }
4389
Mingming Yin514a8bc2014-07-29 15:22:21 -07004390 adev->bt_wb_speech_enabled = false;
4391
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004392 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 *device = &adev->device.common;
4394
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004395 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4396 &adev->streams_output_cfg_list);
4397
Kiran Kandi910e1862013-10-29 13:29:42 -07004398 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004399
4400 char value[PROPERTY_VALUE_MAX];
4401 int trial;
4402 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4403 trial = atoi(value);
4404 if (period_size_is_plausible_for_low_latency(trial)) {
4405 pcm_config_low_latency.period_size = trial;
4406 pcm_config_low_latency.start_threshold = trial / 4;
4407 pcm_config_low_latency.avail_min = trial / 4;
4408 configured_low_latency_capture_period_size = trial;
4409 }
4410 }
4411 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4412 trial = atoi(value);
4413 if (period_size_is_plausible_for_low_latency(trial)) {
4414 configured_low_latency_capture_period_size = trial;
4415 }
4416 }
4417
vivek mehta446c3962015-09-14 10:57:35 -07004418 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004419 pthread_mutex_unlock(&adev_init_lock);
4420
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004421 if (adev->adm_init)
4422 adev->adm_data = adev->adm_init();
4423
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304424 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004425 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426 return 0;
4427}
4428
4429static struct hw_module_methods_t hal_module_methods = {
4430 .open = adev_open,
4431};
4432
4433struct audio_module HAL_MODULE_INFO_SYM = {
4434 .common = {
4435 .tag = HARDWARE_MODULE_TAG,
4436 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4437 .hal_api_version = HARDWARE_HAL_API_VERSION,
4438 .id = AUDIO_HARDWARE_MODULE_ID,
4439 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004440 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 .methods = &hal_module_methods,
4442 },
4443};