blob: 59d14aaf6576d847e8cfd0e3ac78efd6d1198a56 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, 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"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053079#ifdef DYNAMIC_LOG_ENABLED
80#include <log_xml_parser.h>
81#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
82#include <log_utils.h>
83#endif
84
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053086/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
87#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053089#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070091#define PROXY_OPEN_RETRY_COUNT 100
92#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080093
Mingming Yin08c7e312015-03-16 18:10:58 -070094#ifdef USE_LL_AS_PRIMARY_OUTPUT
95#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
96#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
97#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080098#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070099#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
100#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700102#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
103
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700104static unsigned int configured_low_latency_capture_period_size =
105 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
108 .channels = 2,
109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
119 .channels = 2,
120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = 2,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
154struct pcm_config pcm_config_audio_capture = {
155 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158};
159
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700160struct pcm_config pcm_config_audio_capture_rt = {
161 .channels = 2,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = ULL_PERIOD_SIZE,
164 .period_count = 512,
165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = 0,
167 .stop_threshold = INT_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = ULL_PERIOD_SIZE, //1 ms
171};
172
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700173#define AFE_PROXY_CHANNEL_COUNT 2
174#define AFE_PROXY_SAMPLING_RATE 48000
175
176#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
177#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_playback = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
183 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
188};
189
190#define AFE_PROXY_RECORD_PERIOD_SIZE 768
191#define AFE_PROXY_RECORD_PERIOD_COUNT 4
192
193struct pcm_config pcm_config_afe_proxy_record = {
194 .channels = AFE_PROXY_CHANNEL_COUNT,
195 .rate = AFE_PROXY_SAMPLING_RATE,
196 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
197 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
200 .stop_threshold = INT_MAX,
201 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
202};
203
Ashish Jainf1eaa582016-05-23 20:54:24 +0530204#define AUDIO_MAX_PCM_FORMATS 7
205
206const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
207 [AUDIO_FORMAT_DEFAULT] = 0,
208 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
209 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
210 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
211 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
212 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
213 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
214};
215
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800216const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700217 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
218 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700219 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
220 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700221 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700222 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
228 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
229 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
230 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700231
Eric Laurentb23d5282013-05-14 15:27:20 -0700232 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700233 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530234 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
235 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
236 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700238 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700239 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700243
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800247 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800250 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700251 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
252 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
253 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800254 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
255 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
256 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
257
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700258 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
259 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700260 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
261 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700262
263 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
264 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700265 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700266};
267
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700268static const audio_usecase_t offload_usecases[] = {
269 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
274 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
275 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
276 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
277 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700278};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800279
280#define STRING_TO_ENUM(string) { #string, string }
281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800282struct string_to_enum {
283 const char *name;
284 uint32_t value;
285};
286
287static const struct string_to_enum out_channels_name_to_enum_table[] = {
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700292 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800293 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
294 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
296};
297
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700298static const struct string_to_enum out_formats_name_to_enum_table[] = {
299 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
300 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
301 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700302 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800303 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
304 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700305 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800306};
307
308//list of all supported sample rates by HDMI specification.
309static const int out_hdmi_sample_rates[] = {
310 32000, 44100, 48000, 88200, 96000, 176400, 192000,
311};
312
313static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
314 STRING_TO_ENUM(32000),
315 STRING_TO_ENUM(44100),
316 STRING_TO_ENUM(48000),
317 STRING_TO_ENUM(88200),
318 STRING_TO_ENUM(96000),
319 STRING_TO_ENUM(176400),
320 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700321};
322
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700323static struct audio_device *adev = NULL;
324static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700325static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700326//cache last MBDRC cal step level
327static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700328
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700329static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
330 int flags __unused)
331{
332 int dir = 0;
333 switch (uc_id) {
334 case USECASE_AUDIO_RECORD_LOW_LATENCY:
335 dir = 1;
336 case USECASE_AUDIO_PLAYBACK_ULL:
337 break;
338 default:
339 return false;
340 }
341
342 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
343 PCM_PLAYBACK : PCM_CAPTURE);
344 if (adev->adm_is_noirq_avail)
345 return adev->adm_is_noirq_avail(adev->adm_data,
346 adev->snd_card, dev_id, dir);
347 return false;
348}
349
350static void register_out_stream(struct stream_out *out)
351{
352 struct audio_device *adev = out->dev;
353 if (is_offload_usecase(out->usecase) ||
354 !adev->adm_register_output_stream)
355 return;
356
357 // register stream first for backward compatibility
358 adev->adm_register_output_stream(adev->adm_data,
359 out->handle,
360 out->flags);
361
362 if (!adev->adm_set_config)
363 return;
364
365 if (out->realtime)
366 adev->adm_set_config(adev->adm_data,
367 out->handle,
368 out->pcm, &out->config);
369}
370
371static void register_in_stream(struct stream_in *in)
372{
373 struct audio_device *adev = in->dev;
374 if (!adev->adm_register_input_stream)
375 return;
376
377 adev->adm_register_input_stream(adev->adm_data,
378 in->capture_handle,
379 in->flags);
380
381 if (!adev->adm_set_config)
382 return;
383
384 if (in->realtime)
385 adev->adm_set_config(adev->adm_data,
386 in->capture_handle,
387 in->pcm,
388 &in->config);
389}
390
391static void request_out_focus(struct stream_out *out, long ns)
392{
393 struct audio_device *adev = out->dev;
394
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700395 if (adev->adm_request_focus_v2)
396 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
397 else if (adev->adm_request_focus)
398 adev->adm_request_focus(adev->adm_data, out->handle);
399}
400
401static void request_in_focus(struct stream_in *in, long ns)
402{
403 struct audio_device *adev = in->dev;
404
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700405 if (adev->adm_request_focus_v2)
406 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
407 else if (adev->adm_request_focus)
408 adev->adm_request_focus(adev->adm_data, in->capture_handle);
409}
410
411static void release_out_focus(struct stream_out *out)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530426static int parse_snd_card_status(struct str_parms *parms, int *card,
427 card_status_t *status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehtaa76401a2015-04-24 14:12:15 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700449 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700456
457 // if cal set fails, cache level info
458 // if cal set succeds, reset known last cal set
459 if (!ret_val)
460 last_known_cal_step = level;
461 else if (last_known_cal_step != -1)
462 last_known_cal_step = -1;
463
vivek mehtaa76401a2015-04-24 14:12:15 -0700464 pthread_mutex_unlock(&adev->lock);
465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 return ret_val;
472}
473
Ashish Jain5106d362016-05-11 19:23:33 +0530474static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
475{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800476 bool gapless_enabled = false;
477 const char *mixer_ctl_name = "Compress Gapless Playback";
478 struct mixer_ctl *ctl;
479
480 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700481 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530482
483 /*Disable gapless if its AV playback*/
484 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800485
486 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
487 if (!ctl) {
488 ALOGE("%s: Could not get ctl for mixer cmd - %s",
489 __func__, mixer_ctl_name);
490 return -EINVAL;
491 }
492
493 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
494 ALOGE("%s: Could not set gapless mode %d",
495 __func__, gapless_enabled);
496 return -EINVAL;
497 }
498 return 0;
499}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700500
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700501__attribute__ ((visibility ("default")))
502int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
503 int table_size) {
504 int ret_val = 0;
505 ALOGV("%s: enter ... ", __func__);
506
507 pthread_mutex_lock(&adev_init_lock);
508 if (adev == NULL) {
509 ALOGW("%s: adev is NULL .... ", __func__);
510 goto done;
511 }
512
513 pthread_mutex_lock(&adev->lock);
514 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
515 pthread_mutex_unlock(&adev->lock);
516done:
517 pthread_mutex_unlock(&adev_init_lock);
518 ALOGV("%s: exit ... ", __func__);
519 return ret_val;
520}
521
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522static bool is_supported_format(audio_format_t format)
523{
Eric Laurent86e17132013-09-12 17:49:30 -0700524 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530525 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530526 format == AUDIO_FORMAT_AAC_LC ||
527 format == AUDIO_FORMAT_AAC_HE_V1 ||
528 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530529 format == AUDIO_FORMAT_AAC_ADTS_LC ||
530 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
531 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530532 format == AUDIO_FORMAT_AAC_LATM_LC ||
533 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
534 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530535 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
536 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530537 format == AUDIO_FORMAT_PCM_FLOAT ||
538 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700539 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530540 format == AUDIO_FORMAT_AC3 ||
541 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700542 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530543 format == AUDIO_FORMAT_DTS ||
544 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800545 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530546 format == AUDIO_FORMAT_ALAC ||
547 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530548 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530549 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800550 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530551 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700552 format == AUDIO_FORMAT_APTX ||
553 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800554 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700555
556 return false;
557}
558
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700559static inline bool is_mmap_usecase(audio_usecase_t uc_id)
560{
561 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
562 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
563}
564
Avinash Vaish71a8b972014-07-24 15:36:33 +0530565static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
566 struct audio_usecase *uc_info)
567{
568 struct listnode *node;
569 struct audio_usecase *usecase;
570
571 if (uc_info == NULL)
572 return -EINVAL;
573
574 /* Re-route all voice usecases on the shared backend other than the
575 specified usecase to new snd devices */
576 list_for_each(node, &adev->usecase_list) {
577 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800578 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530579 enable_audio_route(adev, usecase);
580 }
581 return 0;
582}
583
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530584static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530585{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530586 ALOGV("%s", __func__);
587 audio_route_apply_and_update_path(adev->audio_route,
588 "asrc-mode");
589 adev->asrc_mode_enabled = true;
590}
591
592static void disable_asrc_mode(struct audio_device *adev)
593{
594 ALOGV("%s", __func__);
595 audio_route_reset_and_update_path(adev->audio_route,
596 "asrc-mode");
597 adev->asrc_mode_enabled = false;
598}
599
600/*
601 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
602 * 44.1 or Native DSD backends are enabled for any of current use case.
603 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
604 * - Disable current mix path use case(Headphone backend) and re-enable it with
605 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
606 * e.g. Naitve DSD or Headphone 44.1 -> + 48
607 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530608static void check_and_set_asrc_mode(struct audio_device *adev,
609 struct audio_usecase *uc_info,
610 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530611{
612 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530613 int i, num_new_devices = 0;
614 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
615 /*
616 *Split snd device for new combo use case
617 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
618 */
619 if (platform_split_snd_device(adev->platform,
620 snd_device,
621 &num_new_devices,
622 split_new_snd_devices) == 0) {
623 for (i = 0; i < num_new_devices; i++)
624 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
625 } else {
626 int new_backend_idx = platform_get_backend_index(snd_device);
627 if (((new_backend_idx == HEADPHONE_BACKEND) ||
628 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
629 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
630 !adev->asrc_mode_enabled) {
631 struct listnode *node = NULL;
632 struct audio_usecase *uc = NULL;
633 struct stream_out *curr_out = NULL;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
635 int i, num_devices, ret = 0;
636 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530637
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530638 list_for_each(node, &adev->usecase_list) {
639 uc = node_to_item(node, struct audio_usecase, list);
640 curr_out = (struct stream_out*) uc->stream.out;
641 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
642 /*
643 *Split snd device for existing combo use case
644 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
645 */
646 ret = platform_split_snd_device(adev->platform,
647 uc->out_snd_device,
648 &num_devices,
649 split_snd_devices);
650 if (ret < 0 || num_devices == 0) {
651 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
652 split_snd_devices[0] = uc->out_snd_device;
653 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800654 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530655 for (i = 0; i < num_devices; i++) {
656 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
657 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
658 if((new_backend_idx == HEADPHONE_BACKEND) &&
659 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
660 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
661 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
662 __func__);
663 enable_asrc_mode(adev);
664 break;
665 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
666 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
667 (usecase_backend_idx == HEADPHONE_BACKEND)) {
668 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
669 __func__);
670 disable_audio_route(adev, uc);
671 disable_snd_device(adev, uc->out_snd_device);
672 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
673 if (new_backend_idx == DSD_NATIVE_BACKEND)
674 audio_route_apply_and_update_path(adev->audio_route,
675 "hph-true-highquality-mode");
676 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
677 (curr_out->bit_width >= 24))
678 audio_route_apply_and_update_path(adev->audio_route,
679 "hph-highquality-mode");
680 enable_asrc_mode(adev);
681 enable_snd_device(adev, uc->out_snd_device);
682 enable_audio_route(adev, uc);
683 break;
684 }
685 }
686 // reset split devices count
687 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800688 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530689 if (adev->asrc_mode_enabled)
690 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530691 }
692 }
693 }
694}
695
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700696int pcm_ioctl(struct pcm *pcm, int request, ...)
697{
698 va_list ap;
699 void * arg;
700 int pcm_fd = *(int*)pcm;
701
702 va_start(ap, request);
703 arg = va_arg(ap, void *);
704 va_end(ap);
705
706 return ioctl(pcm_fd, request, arg);
707}
708
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700709int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700710 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800711{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700713 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530714 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800715
716 if (usecase == NULL)
717 return -EINVAL;
718
719 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
720
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800721 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800723 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800725
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800726#ifdef DS1_DOLBY_DAP_ENABLED
727 audio_extn_dolby_set_dmid(adev);
728 audio_extn_dolby_set_endpoint(adev);
729#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700730 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700731 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530732 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700733 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530734 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530735 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
736 out = usecase->stream.out;
737 if (out && out->compr)
738 audio_extn_utils_compress_set_clk_rec_mode(usecase);
739 }
740
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800741 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700742 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700743 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700744 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745 ALOGV("%s: exit", __func__);
746 return 0;
747}
748
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700749int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700750 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700753 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800754
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530755 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800756 return -EINVAL;
757
758 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 if (usecase->type == PCM_CAPTURE)
760 snd_device = usecase->in_snd_device;
761 else
762 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800763 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700764 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700765 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700766 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700767 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530768 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769 ALOGV("%s: exit", __func__);
770 return 0;
771}
772
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700773int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700774 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530776 int i, num_devices = 0;
777 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700778 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
779
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 if (snd_device < SND_DEVICE_MIN ||
781 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800782 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800783 return -EINVAL;
784 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700785
786 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700787
788 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
789 ALOGE("%s: Invalid sound device returned", __func__);
790 return -EINVAL;
791 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700793 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700794 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 return 0;
796 }
797
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530798
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700799 if (audio_extn_spkr_prot_is_enabled())
800 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700801
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800802 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
803 audio_extn_spkr_prot_is_enabled()) {
804 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700805 adev->snd_dev_ref_cnt[snd_device]--;
806 return -EINVAL;
807 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200808 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800809 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800810 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200811 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800812 return -EINVAL;
813 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700814 } else if (platform_split_snd_device(adev->platform,
815 snd_device,
816 &num_devices,
817 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530818 for (i = 0; i < num_devices; i++) {
819 enable_snd_device(adev, new_snd_devices[i]);
820 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800821 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700822 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530823
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530824
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530825 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
826 (audio_extn_a2dp_start_playback() < 0)) {
827 ALOGE(" fail to configure A2dp control path ");
828 return -EINVAL;
829 }
830
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700831 /* due to the possibility of calibration overwrite between listen
832 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700833 audio_extn_sound_trigger_update_device_status(snd_device,
834 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530835 audio_extn_listen_update_device_status(snd_device,
836 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700837 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700838 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700839 audio_extn_sound_trigger_update_device_status(snd_device,
840 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530841 audio_extn_listen_update_device_status(snd_device,
842 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700843 return -EINVAL;
844 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300845 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700846 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530847
848 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
849 !adev->native_playback_enabled &&
850 audio_is_true_native_stream_active(adev)) {
851 ALOGD("%s: %d: napb: enabling native mode in hardware",
852 __func__, __LINE__);
853 audio_route_apply_and_update_path(adev->audio_route,
854 "true-native-mode");
855 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858 return 0;
859}
860
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700861int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700862 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530864 int i, num_devices = 0;
865 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700866 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
867
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800868 if (snd_device < SND_DEVICE_MIN ||
869 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800870 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800871 return -EINVAL;
872 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
874 ALOGE("%s: device ref cnt is already 0", __func__);
875 return -EINVAL;
876 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700879
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700880 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
881 ALOGE("%s: Invalid sound device returned", __func__);
882 return -EINVAL;
883 }
884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700886 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530887
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800888 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
889 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700890 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700891 } else if (platform_split_snd_device(adev->platform,
892 snd_device,
893 &num_devices,
894 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530895 for (i = 0; i < num_devices; i++) {
896 disable_snd_device(adev, new_snd_devices[i]);
897 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300898 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700899 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300900 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700901
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530902 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
903 audio_extn_a2dp_stop_playback();
904
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700905 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530906 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530907 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
908 adev->native_playback_enabled) {
909 ALOGD("%s: %d: napb: disabling native mode in hardware",
910 __func__, __LINE__);
911 audio_route_reset_and_update_path(adev->audio_route,
912 "true-native-mode");
913 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530914 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
915 adev->asrc_mode_enabled) {
916 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 disable_asrc_mode(adev);
918 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530919 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530920
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200921 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700922 audio_extn_sound_trigger_update_device_status(snd_device,
923 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530924 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800925 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 return 0;
929}
930
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700931/*
932 legend:
933 uc - existing usecase
934 new_uc - new usecase
935 d1, d11, d2 - SND_DEVICE enums
936 a1, a2 - corresponding ANDROID device enums
937 B1, B2 - backend strings
938
939case 1
940 uc->dev d1 (a1) B1
941 new_uc->dev d1 (a1), d2 (a2) B1, B2
942
943 resolution: disable and enable uc->dev on d1
944
945case 2
946 uc->dev d1 (a1) B1
947 new_uc->dev d11 (a1) B1
948
949 resolution: need to switch uc since d1 and d11 are related
950 (e.g. speaker and voice-speaker)
951 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
952
953case 3
954 uc->dev d1 (a1) B1
955 new_uc->dev d2 (a2) B2
956
957 resolution: no need to switch uc
958
959case 4
960 uc->dev d1 (a1) B1
961 new_uc->dev d2 (a2) B1
962
963 resolution: disable enable uc-dev on d2 since backends match
964 we cannot enable two streams on two different devices if they
965 share the same backend. e.g. if offload is on speaker device using
966 QUAD_MI2S backend and a low-latency stream is started on voice-handset
967 using the same backend, offload must also be switched to voice-handset.
968
969case 5
970 uc->dev d1 (a1) B1
971 new_uc->dev d1 (a1), d2 (a2) B1
972
973 resolution: disable enable uc-dev on d2 since backends match
974 we cannot enable two streams on two different devices if they
975 share the same backend.
976
977case 6
978 uc->dev d1 (a1) B1
979 new_uc->dev d2 (a1) B2
980
981 resolution: no need to switch
982
983case 7
984 uc->dev d1 (a1), d2 (a2) B1, B2
985 new_uc->dev d1 (a1) B1
986
987 resolution: no need to switch
988
989*/
990static snd_device_t derive_playback_snd_device(void * platform,
991 struct audio_usecase *uc,
992 struct audio_usecase *new_uc,
993 snd_device_t new_snd_device)
994{
995 audio_devices_t a1 = uc->stream.out->devices;
996 audio_devices_t a2 = new_uc->stream.out->devices;
997
998 snd_device_t d1 = uc->out_snd_device;
999 snd_device_t d2 = new_snd_device;
1000
1001 // Treat as a special case when a1 and a2 are not disjoint
1002 if ((a1 != a2) && (a1 & a2)) {
1003 snd_device_t d3[2];
1004 int num_devices = 0;
1005 int ret = platform_split_snd_device(platform,
1006 popcount(a1) > 1 ? d1 : d2,
1007 &num_devices,
1008 d3);
1009 if (ret < 0) {
1010 if (ret != -ENOSYS) {
1011 ALOGW("%s failed to split snd_device %d",
1012 __func__,
1013 popcount(a1) > 1 ? d1 : d2);
1014 }
1015 goto end;
1016 }
1017
1018 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1019 // But if it does happen, we need to give priority to d2 if
1020 // the combo devices active on the existing usecase share a backend.
1021 // This is because we cannot have a usecase active on a combo device
1022 // and a new usecase requests one device in this combo pair.
1023 if (platform_check_backends_match(d3[0], d3[1])) {
1024 return d2; // case 5
1025 } else {
1026 return d1; // case 1
1027 }
1028 } else {
1029 if (platform_check_backends_match(d1, d2)) {
1030 return d2; // case 2, 4
1031 } else {
1032 return d1; // case 6, 3
1033 }
1034 }
1035
1036end:
1037 return d2; // return whatever was calculated before.
1038}
1039
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301041 struct audio_usecase *uc_info,
1042 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043{
1044 struct listnode *node;
1045 struct audio_usecase *usecase;
1046 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301047 snd_device_t uc_derive_snd_device;
1048 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001050 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301051 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 /*
1053 * This function is to make sure that all the usecases that are active on
1054 * the hardware codec backend are always routed to any one device that is
1055 * handled by the hardware codec.
1056 * For example, if low-latency and deep-buffer usecases are currently active
1057 * on speaker and out_set_parameters(headset) is received on low-latency
1058 * output, then we have to make sure deep-buffer is also switched to headset,
1059 * because of the limitation that both the devices cannot be enabled
1060 * at the same time as they share the same backend.
1061 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001062 /*
1063 * This call is to check if we need to force routing for a particular stream
1064 * If there is a backend configuration change for the device when a
1065 * new stream starts, then ADM needs to be closed and re-opened with the new
1066 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001067 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001068 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001069 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1070 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301071 /* For a2dp device reconfigure all active sessions
1072 * with new AFE encoder format based on a2dp state
1073 */
1074 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1075 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1076 audio_extn_a2dp_is_force_device_switch()) {
1077 force_routing = true;
1078 force_restart_session = true;
1079 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301080 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1081
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001083 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001084 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1086 switch_device[i] = false;
1087
1088 list_for_each(node, &adev->usecase_list) {
1089 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001090
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301091 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1092 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301093 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301094 platform_get_snd_device_name(usecase->out_snd_device),
1095 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301096 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1097 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1098 usecase, uc_info, snd_device);
1099 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1100 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1101 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1102 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1103 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1104 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1105 ((force_restart_session) ||
1106 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301107 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1108 __func__, use_case_table[usecase->id],
1109 platform_get_snd_device_name(usecase->out_snd_device));
1110 disable_audio_route(adev, usecase);
1111 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301112 /* Enable existing usecase on derived playback device */
1113 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301114 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 }
1117 }
1118
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301119 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1120 num_uc_to_switch);
1121
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001123 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301125 /* Make sure the previous devices to be disabled first and then enable the
1126 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127 list_for_each(node, &adev->usecase_list) {
1128 usecase = node_to_item(node, struct audio_usecase, list);
1129 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001130 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 }
1132 }
1133
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001134 list_for_each(node, &adev->usecase_list) {
1135 usecase = node_to_item(node, struct audio_usecase, list);
1136 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301137 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001138 }
1139 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 /* Re-route all the usecases on the shared backend other than the
1142 specified usecase to new snd devices */
1143 list_for_each(node, &adev->usecase_list) {
1144 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301145 /* Update the out_snd_device only before enabling the audio route */
1146 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301147 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301148 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301149 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301150 use_case_table[usecase->id],
1151 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001152 /* Update voc calibration before enabling VoIP route */
1153 if (usecase->type == VOIP_CALL)
1154 status = platform_switch_voice_call_device_post(adev->platform,
1155 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001156 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301157 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301158 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 }
1160 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161 }
1162}
1163
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301164static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 struct audio_usecase *uc_info,
1166 snd_device_t snd_device)
1167{
1168 struct listnode *node;
1169 struct audio_usecase *usecase;
1170 bool switch_device[AUDIO_USECASE_MAX];
1171 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301172 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001173 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001174
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301175 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1176 snd_device);
1177 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301178
1179 /*
1180 * Make sure out devices is checked against out codec backend device and
1181 * also in devices against in codec backend. Checking out device against in
1182 * codec backend or vice versa causes issues.
1183 */
1184 if (uc_info->type == PCM_CAPTURE)
1185 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001186 /*
1187 * This function is to make sure that all the active capture usecases
1188 * are always routed to the same input sound device.
1189 * For example, if audio-record and voice-call usecases are currently
1190 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1191 * is received for voice call then we have to make sure that audio-record
1192 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1193 * because of the limitation that two devices cannot be enabled
1194 * at the same time if they share the same backend.
1195 */
1196 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1197 switch_device[i] = false;
1198
1199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301201 /*
1202 * TODO: Enhance below condition to handle BT sco/USB multi recording
1203 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001204 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301206 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301207 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301208 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301209 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001210 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001211 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1212 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001213 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001214 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 switch_device[usecase->id] = true;
1216 num_uc_to_switch++;
1217 }
1218 }
1219
1220 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001221 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001222
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301223 /* Make sure the previous devices to be disabled first and then enable the
1224 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001225 list_for_each(node, &adev->usecase_list) {
1226 usecase = node_to_item(node, struct audio_usecase, list);
1227 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001228 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001229 }
1230 }
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001235 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 }
1237 }
1238
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001239 /* Re-route all the usecases on the shared backend other than the
1240 specified usecase to new snd devices */
1241 list_for_each(node, &adev->usecase_list) {
1242 usecase = node_to_item(node, struct audio_usecase, list);
1243 /* Update the in_snd_device only before enabling the audio route */
1244 if (switch_device[usecase->id] ) {
1245 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001246 if (usecase->type != VOICE_CALL) {
1247 /* Update voc calibration before enabling VoIP route */
1248 if (usecase->type == VOIP_CALL)
1249 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001250 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001251 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301252 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001253 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001254 }
1255 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001256 }
1257}
1258
Mingming Yin3a941d42016-02-17 18:08:05 -08001259static void reset_hdmi_sink_caps(struct stream_out *out) {
1260 int i = 0;
1261
1262 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1263 out->supported_channel_masks[i] = 0;
1264 }
1265 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1266 out->supported_formats[i] = 0;
1267 }
1268 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1269 out->supported_sample_rates[i] = 0;
1270 }
1271}
1272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001274static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275{
Mingming Yin3a941d42016-02-17 18:08:05 -08001276 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001277 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Mingming Yin3a941d42016-02-17 18:08:05 -08001279 reset_hdmi_sink_caps(out);
1280
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001281 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001282 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001283 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001284 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001285 }
1286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001289 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1292 case 6:
1293 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1294 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1295 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1296 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1297 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1298 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001299 break;
1300 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001301 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001302 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303 break;
1304 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001305
1306 // check channel format caps
1307 i = 0;
1308 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1309 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1310 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1311 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1312 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1313 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1314 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1315 }
1316
Ben Romberger1aaaf862017-04-06 17:49:46 -07001317 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1318 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1319 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1320 }
1321
Mingming Yin3a941d42016-02-17 18:08:05 -08001322 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1323 ALOGV(":%s HDMI supports DTS format", __func__);
1324 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1325 }
1326
1327 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1328 ALOGV(":%s HDMI supports DTS HD format", __func__);
1329 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1330 }
1331
Naresh Tanniru928f0862017-04-07 16:44:23 -07001332 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1333 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1334 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1335 }
1336
Mingming Yin3a941d42016-02-17 18:08:05 -08001337
1338 // check sample rate caps
1339 i = 0;
1340 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1341 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1342 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1343 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1344 }
1345 }
1346
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001347 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348}
1349
Alexy Josephb1379942016-01-29 15:49:38 -08001350audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001351 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001352{
1353 struct audio_usecase *usecase;
1354 struct listnode *node;
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001358 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001359 ALOGV("%s: usecase id %d", __func__, usecase->id);
1360 return usecase->id;
1361 }
1362 }
1363 return USECASE_INVALID;
1364}
1365
Alexy Josephb1379942016-01-29 15:49:38 -08001366struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001367 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368{
1369 struct audio_usecase *usecase;
1370 struct listnode *node;
1371
1372 list_for_each(node, &adev->usecase_list) {
1373 usecase = node_to_item(node, struct audio_usecase, list);
1374 if (usecase->id == uc_id)
1375 return usecase;
1376 }
1377 return NULL;
1378}
1379
Dhananjay Kumard4833242016-10-06 22:09:12 +05301380struct stream_in *get_next_active_input(const struct audio_device *adev)
1381{
1382 struct audio_usecase *usecase;
1383 struct listnode *node;
1384
1385 list_for_each_reverse(node, &adev->usecase_list) {
1386 usecase = node_to_item(node, struct audio_usecase, list);
1387 if (usecase->type == PCM_CAPTURE)
1388 return usecase->stream.in;
1389 }
1390 return NULL;
1391}
1392
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301393/*
1394 * is a true native playback active
1395 */
1396bool audio_is_true_native_stream_active(struct audio_device *adev)
1397{
1398 bool active = false;
1399 int i = 0;
1400 struct listnode *node;
1401
1402 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1403 ALOGV("%s:napb: not in true mode or non hdphones device",
1404 __func__);
1405 active = false;
1406 goto exit;
1407 }
1408
1409 list_for_each(node, &adev->usecase_list) {
1410 struct audio_usecase *uc;
1411 uc = node_to_item(node, struct audio_usecase, list);
1412 struct stream_out *curr_out =
1413 (struct stream_out*) uc->stream.out;
1414
1415 if (curr_out && PCM_PLAYBACK == uc->type) {
1416 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1417 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1418 uc->id, curr_out->sample_rate,
1419 curr_out->bit_width,
1420 platform_get_snd_device_name(uc->out_snd_device));
1421
1422 if (is_offload_usecase(uc->id) &&
1423 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1424 active = true;
1425 ALOGD("%s:napb:native stream detected", __func__);
1426 }
1427 }
1428 }
1429exit:
1430 return active;
1431}
1432
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301433/*
1434 * if native DSD playback active
1435 */
1436bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1437{
1438 bool active = false;
1439 struct listnode *node = NULL;
1440 struct audio_usecase *uc = NULL;
1441 struct stream_out *curr_out = NULL;
1442
1443 list_for_each(node, &adev->usecase_list) {
1444 uc = node_to_item(node, struct audio_usecase, list);
1445 curr_out = (struct stream_out*) uc->stream.out;
1446
1447 if (curr_out && PCM_PLAYBACK == uc->type &&
1448 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1449 active = true;
1450 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301451 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301452 }
1453 }
1454 return active;
1455}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301456
1457static bool force_device_switch(struct audio_usecase *usecase)
1458{
1459 bool ret = false;
1460 bool is_it_true_mode = false;
1461
1462 if (is_offload_usecase(usecase->id) &&
1463 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001464 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1465 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1466 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301467 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1468 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1469 (!is_it_true_mode && adev->native_playback_enabled)){
1470 ret = true;
1471 ALOGD("napb: time to toggle native mode");
1472 }
1473 }
1474
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301475 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301476 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1477 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301478 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001479 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301480 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301481 ALOGD("Force a2dp device switch to update new encoder config");
1482 ret = true;
1483 }
1484
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301485 return ret;
1486}
1487
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001488int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001490 snd_device_t out_snd_device = SND_DEVICE_NONE;
1491 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492 struct audio_usecase *usecase = NULL;
1493 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001494 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001495 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001496 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301499 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1500
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 usecase = get_usecase_from_list(adev, uc_id);
1502 if (usecase == NULL) {
1503 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1504 return -EINVAL;
1505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001507 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001508 (usecase->type == VOIP_CALL) ||
1509 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301510 if(usecase->stream.out == NULL) {
1511 ALOGE("%s: stream.out is NULL", __func__);
1512 return -EINVAL;
1513 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001514 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001515 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 usecase->devices = usecase->stream.out->devices;
1518 } else {
1519 /*
1520 * If the voice call is active, use the sound devices of voice call usecase
1521 * so that it would not result any device switch. All the usecases will
1522 * be switched to new device when select_devices() is called for voice call
1523 * usecase. This is to avoid switching devices for voice call when
1524 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001525 * choose voice call device only if the use case device is
1526 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001528 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001529 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001530 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001531 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1532 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301533 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1534 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001535 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 in_snd_device = vc_usecase->in_snd_device;
1537 out_snd_device = vc_usecase->out_snd_device;
1538 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001539 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001540 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001541 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001542 if ((voip_usecase != NULL) &&
1543 (usecase->type == PCM_PLAYBACK) &&
1544 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001545 out_snd_device_backend_match = platform_check_backends_match(
1546 voip_usecase->out_snd_device,
1547 platform_get_output_snd_device(
1548 adev->platform,
1549 usecase->stream.out));
1550 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001551 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001552 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1553 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001554 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001555 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001556 in_snd_device = voip_usecase->in_snd_device;
1557 out_snd_device = voip_usecase->out_snd_device;
1558 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001559 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001560 hfp_ucid = audio_extn_hfp_get_usecase();
1561 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001562 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001563 in_snd_device = hfp_usecase->in_snd_device;
1564 out_snd_device = hfp_usecase->out_snd_device;
1565 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 }
1567 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301568 if (usecase->stream.out == NULL) {
1569 ALOGE("%s: stream.out is NULL", __func__);
1570 return -EINVAL;
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 usecase->devices = usecase->stream.out->devices;
1573 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001574 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001575 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001576 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001577 if (usecase->stream.out == adev->primary_output &&
1578 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001579 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001580 select_devices(adev, adev->active_input->usecase);
1581 }
1582 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301584 if (usecase->stream.in == NULL) {
1585 ALOGE("%s: stream.in is NULL", __func__);
1586 return -EINVAL;
1587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588 usecase->devices = usecase->stream.in->device;
1589 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001590 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001592 if (adev->active_input &&
1593 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301594 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1595 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1596 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001597 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001598 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001599 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1600 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001601 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001602 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001603 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604 }
1605 }
1606
1607 if (out_snd_device == usecase->out_snd_device &&
1608 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301609
1610 if (!force_device_switch(usecase))
1611 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 }
1613
sangwoobc677242013-08-08 16:53:43 +09001614 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001615 out_snd_device, platform_get_snd_device_name(out_snd_device),
1616 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 /*
1619 * Limitation: While in call, to do a device switch we need to disable
1620 * and enable both RX and TX devices though one of them is same as current
1621 * device.
1622 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001623 if ((usecase->type == VOICE_CALL) &&
1624 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1625 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001626 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001627 }
1628
1629 if (((usecase->type == VOICE_CALL) ||
1630 (usecase->type == VOIP_CALL)) &&
1631 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1632 /* Disable sidetone only if voice/voip call already exists */
1633 if (voice_is_call_state_active(adev) ||
1634 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001635 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001636
1637 /* Disable aanc only if voice call exists */
1638 if (voice_is_call_state_active(adev))
1639 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001640 }
1641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 /* Disable current sound devices */
1643 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001644 disable_audio_route(adev, usecase);
1645 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001649 disable_audio_route(adev, usecase);
1650 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 }
1652
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001653 /* Applicable only on the targets that has external modem.
1654 * New device information should be sent to modem before enabling
1655 * the devices to reduce in-call device switch time.
1656 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001657 if ((usecase->type == VOICE_CALL) &&
1658 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1659 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001660 status = platform_switch_voice_call_enable_device_config(adev->platform,
1661 out_snd_device,
1662 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001663 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665 /* Enable new sound devices */
1666 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001667 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301668 if (platform_check_codec_asrc_support(adev->platform))
1669 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001670 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001673 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301674 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677
Avinash Vaish71a8b972014-07-24 15:36:33 +05301678 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001679 status = platform_switch_voice_call_device_post(adev->platform,
1680 out_snd_device,
1681 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301682 enable_audio_route_for_voice_usecases(adev, usecase);
1683 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001684
sangwoo170731f2013-06-08 15:36:36 +09001685 usecase->in_snd_device = in_snd_device;
1686 usecase->out_snd_device = out_snd_device;
1687
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301688 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1689 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301690 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001691 if ((24 == usecase->stream.out->bit_width) &&
1692 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1693 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1694 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1695 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1696 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1697 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1698 /*
1699 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1700 * configured device sample rate, if not update the COPP rate to be equal to the
1701 * device sample rate, else open COPP at stream sample rate
1702 */
1703 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1704 usecase->stream.out->sample_rate,
1705 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301706 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1707 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001708 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1709 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1710 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1711 }
1712
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001713 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001714 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001715 audio_extn_gef_notify_device_config(
1716 usecase->stream.out->devices,
1717 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001718 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001719 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001720 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301721 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001722 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001723
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001724 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001725 /* Enable aanc only if voice call exists */
1726 if (voice_is_call_state_active(adev))
1727 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1728
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001729 /* Enable sidetone only if other voice/voip call already exists */
1730 if (voice_is_call_state_active(adev) ||
1731 voice_extn_compress_voip_is_started(adev))
1732 voice_set_sidetone(adev, out_snd_device, true);
1733 }
1734
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001735 /* Applicable only on the targets that has external modem.
1736 * Enable device command should be sent to modem only after
1737 * enabling voice call mixer controls
1738 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001739 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001740 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1741 out_snd_device,
1742 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301743 ALOGD("%s: done",__func__);
1744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 return status;
1746}
1747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748static int stop_input_stream(struct stream_in *in)
1749{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301750 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751 struct audio_usecase *uc_info;
1752 struct audio_device *adev = in->dev;
1753
Eric Laurent994a6932013-07-17 11:51:42 -07001754 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 uc_info = get_usecase_from_list(adev, in->usecase);
1757 if (uc_info == NULL) {
1758 ALOGE("%s: Could not find the usecase (%d) in the list",
1759 __func__, in->usecase);
1760 return -EINVAL;
1761 }
1762
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001763 /* Close in-call recording streams */
1764 voice_check_and_stop_incall_rec_usecase(adev, in);
1765
Eric Laurent150dbfe2013-02-27 14:31:02 -08001766 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001767 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001768
1769 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001770 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001772 list_remove(&uc_info->list);
1773 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001775 adev->active_input = get_next_active_input(adev);
1776
Eric Laurent994a6932013-07-17 11:51:42 -07001777 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 return ret;
1779}
1780
1781int start_input_stream(struct stream_in *in)
1782{
1783 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001784 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 struct audio_usecase *uc_info;
1786 struct audio_device *adev = in->dev;
1787
Mingming Yin2664a5b2015-09-03 10:53:11 -07001788 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1789 if (get_usecase_from_list(adev, usecase) == NULL)
1790 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301791 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1792 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001793
Naresh Tanniru80659832014-06-04 18:17:56 +05301794
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301795 if (CARD_STATUS_OFFLINE == in->card_status||
1796 CARD_STATUS_OFFLINE == adev->card_status) {
1797 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301798 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301799 goto error_config;
1800 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301801
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001802 /* Check if source matches incall recording usecase criteria */
1803 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1804 if (ret)
1805 goto error_config;
1806 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001807 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1808
1809 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1810 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1811 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001812 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001813 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001814
Eric Laurentb23d5282013-05-14 15:27:20 -07001815 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 if (in->pcm_device_id < 0) {
1817 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1818 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001819 ret = -EINVAL;
1820 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
1823 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001825
1826 if (!uc_info) {
1827 ret = -ENOMEM;
1828 goto error_config;
1829 }
1830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 uc_info->id = in->usecase;
1832 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001833 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 uc_info->devices = in->device;
1835 uc_info->in_snd_device = SND_DEVICE_NONE;
1836 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001838 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301839 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1840 adev->perf_lock_opts,
1841 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301844 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1845 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001846
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301847 if (audio_extn_cin_attached_usecase(in->usecase)) {
1848 ret = audio_extn_cin_start_input_stream(in);
1849 if (ret)
1850 goto error_open;
1851 else
1852 goto done_open;
1853 }
1854
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001855 unsigned int flags = PCM_IN;
1856 unsigned int pcm_open_retry_count = 0;
1857
1858 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1859 flags |= PCM_MMAP | PCM_NOIRQ;
1860 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001861 } else if (in->realtime) {
1862 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001863 }
1864
1865 while (1) {
1866 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1867 flags, &in->config);
1868 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1869 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1870 if (in->pcm != NULL) {
1871 pcm_close(in->pcm);
1872 in->pcm = NULL;
1873 }
1874 if (pcm_open_retry_count-- == 0) {
1875 ret = -EIO;
1876 goto error_open;
1877 }
1878 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1879 continue;
1880 }
1881 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001883
1884 ALOGV("%s: pcm_prepare", __func__);
1885 ret = pcm_prepare(in->pcm);
1886 if (ret < 0) {
1887 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1888 pcm_close(in->pcm);
1889 in->pcm = NULL;
1890 goto error_open;
1891 }
1892
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001893 register_in_stream(in);
1894 if (in->realtime) {
1895 ret = pcm_start(in->pcm);
1896 if (ret < 0)
1897 goto error_open;
1898 }
1899
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301900done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301901 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001902 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001903
Eric Laurentc8400632013-02-14 19:04:54 -08001904 return ret;
1905
1906error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301907 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001909error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301910 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301911 /*
1912 * sleep 50ms to allow sufficient time for kernel
1913 * drivers to recover incases like SSR.
1914 */
1915 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001917
1918 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919}
1920
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001921void lock_input_stream(struct stream_in *in)
1922{
1923 pthread_mutex_lock(&in->pre_lock);
1924 pthread_mutex_lock(&in->lock);
1925 pthread_mutex_unlock(&in->pre_lock);
1926}
1927
1928void lock_output_stream(struct stream_out *out)
1929{
1930 pthread_mutex_lock(&out->pre_lock);
1931 pthread_mutex_lock(&out->lock);
1932 pthread_mutex_unlock(&out->pre_lock);
1933}
1934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001935/* must be called with out->lock locked */
1936static int send_offload_cmd_l(struct stream_out* out, int command)
1937{
1938 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1939
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001940 if (!cmd) {
1941 ALOGE("failed to allocate mem for command 0x%x", command);
1942 return -ENOMEM;
1943 }
1944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 ALOGVV("%s %d", __func__, command);
1946
1947 cmd->cmd = command;
1948 list_add_tail(&out->offload_cmd_list, &cmd->node);
1949 pthread_cond_signal(&out->offload_cond);
1950 return 0;
1951}
1952
1953/* must be called iwth out->lock locked */
1954static void stop_compressed_output_l(struct stream_out *out)
1955{
1956 out->offload_state = OFFLOAD_STATE_IDLE;
1957 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001958 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 if (out->compr != NULL) {
1960 compress_stop(out->compr);
1961 while (out->offload_thread_blocked) {
1962 pthread_cond_wait(&out->cond, &out->lock);
1963 }
1964 }
1965}
1966
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001967bool is_offload_usecase(audio_usecase_t uc_id)
1968{
1969 unsigned int i;
1970 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1971 if (uc_id == offload_usecases[i])
1972 return true;
1973 }
1974 return false;
1975}
1976
Dhananjay Kumarac341582017-02-23 23:42:25 +05301977static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001978{
vivek mehta446c3962015-09-14 10:57:35 -07001979 audio_usecase_t ret_uc = USECASE_INVALID;
1980 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001981 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001982 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301983 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001984 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1985 else
1986 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001987
vivek mehta446c3962015-09-14 10:57:35 -07001988 pthread_mutex_lock(&adev->lock);
1989 if (get_usecase_from_list(adev, ret_uc) != NULL)
1990 ret_uc = USECASE_INVALID;
1991 pthread_mutex_unlock(&adev->lock);
1992
1993 return ret_uc;
1994 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995
1996 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001997 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1998 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1999 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2000 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002001 break;
2002 }
2003 }
vivek mehta446c3962015-09-14 10:57:35 -07002004
2005 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2006 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002007}
2008
2009static void free_offload_usecase(struct audio_device *adev,
2010 audio_usecase_t uc_id)
2011{
vivek mehta446c3962015-09-14 10:57:35 -07002012 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002013 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002014
2015 if (!adev->multi_offload_enable)
2016 return;
2017
2018 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2019 if (offload_usecases[offload_uc_index] == uc_id) {
2020 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002021 break;
2022 }
2023 }
2024 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2025}
2026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027static void *offload_thread_loop(void *context)
2028{
2029 struct stream_out *out = (struct stream_out *) context;
2030 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002031 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2034 set_sched_policy(0, SP_FOREGROUND);
2035 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2036
2037 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002038 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 for (;;) {
2040 struct offload_cmd *cmd = NULL;
2041 stream_callback_event_t event;
2042 bool send_callback = false;
2043
2044 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2045 __func__, list_empty(&out->offload_cmd_list),
2046 out->offload_state);
2047 if (list_empty(&out->offload_cmd_list)) {
2048 ALOGV("%s SLEEPING", __func__);
2049 pthread_cond_wait(&out->offload_cond, &out->lock);
2050 ALOGV("%s RUNNING", __func__);
2051 continue;
2052 }
2053
2054 item = list_head(&out->offload_cmd_list);
2055 cmd = node_to_item(item, struct offload_cmd, node);
2056 list_remove(item);
2057
2058 ALOGVV("%s STATE %d CMD %d out->compr %p",
2059 __func__, out->offload_state, cmd->cmd, out->compr);
2060
2061 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2062 free(cmd);
2063 break;
2064 }
2065
2066 if (out->compr == NULL) {
2067 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002068 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 pthread_cond_signal(&out->cond);
2070 continue;
2071 }
2072 out->offload_thread_blocked = true;
2073 pthread_mutex_unlock(&out->lock);
2074 send_callback = false;
2075 switch(cmd->cmd) {
2076 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002077 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002079 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 send_callback = true;
2081 event = STREAM_CBK_EVENT_WRITE_READY;
2082 break;
2083 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002084 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302085 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002086 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302087 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302089 if (ret < 0)
2090 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302091 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302092 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002093 compress_drain(out->compr);
2094 else
2095 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302096 if (ret != -ENETRESET) {
2097 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302098 pthread_mutex_lock(&out->lock);
2099 out->send_new_metadata = 1;
2100 out->send_next_track_params = true;
2101 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302102 event = STREAM_CBK_EVENT_DRAIN_READY;
2103 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2104 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302105 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 break;
2107 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002108 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002110 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 send_callback = true;
2112 event = STREAM_CBK_EVENT_DRAIN_READY;
2113 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302114 case OFFLOAD_CMD_ERROR:
2115 ALOGD("copl(%p): sending error callback to AF", out);
2116 send_callback = true;
2117 event = STREAM_CBK_EVENT_ERROR;
2118 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 default:
2120 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2121 break;
2122 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002123 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 out->offload_thread_blocked = false;
2125 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002126 if (send_callback && out->client_callback) {
2127 ALOGVV("%s: sending client_callback event %d", __func__, event);
2128 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002129 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 free(cmd);
2131 }
2132
2133 pthread_cond_signal(&out->cond);
2134 while (!list_empty(&out->offload_cmd_list)) {
2135 item = list_head(&out->offload_cmd_list);
2136 list_remove(item);
2137 free(node_to_item(item, struct offload_cmd, node));
2138 }
2139 pthread_mutex_unlock(&out->lock);
2140
2141 return NULL;
2142}
2143
2144static int create_offload_callback_thread(struct stream_out *out)
2145{
2146 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2147 list_init(&out->offload_cmd_list);
2148 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2149 offload_thread_loop, out);
2150 return 0;
2151}
2152
2153static int destroy_offload_callback_thread(struct stream_out *out)
2154{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002155 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 stop_compressed_output_l(out);
2157 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2158
2159 pthread_mutex_unlock(&out->lock);
2160 pthread_join(out->offload_thread, (void **) NULL);
2161 pthread_cond_destroy(&out->offload_cond);
2162
2163 return 0;
2164}
2165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166static int stop_output_stream(struct stream_out *out)
2167{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302168 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 struct audio_usecase *uc_info;
2170 struct audio_device *adev = out->dev;
2171
Eric Laurent994a6932013-07-17 11:51:42 -07002172 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002173 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 uc_info = get_usecase_from_list(adev, out->usecase);
2175 if (uc_info == NULL) {
2176 ALOGE("%s: Could not find the usecase (%d) in the list",
2177 __func__, out->usecase);
2178 return -EINVAL;
2179 }
2180
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002181 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302182 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002183 if (adev->visualizer_stop_output != NULL)
2184 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002185
2186 audio_extn_dts_remove_state_notifier_node(out->usecase);
2187
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002188 if (adev->offload_effects_stop_output != NULL)
2189 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2190 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002191
Eric Laurent150dbfe2013-02-27 14:31:02 -08002192 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002194
2195 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002196 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002198 list_remove(&uc_info->list);
2199 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002201 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302202 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002203 ALOGV("Disable passthrough , reset mixer to pcm");
2204 /* NO_PASSTHROUGH */
2205 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002206 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002207 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2208 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002209
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302210 /* Must be called after removing the usecase from list */
2211 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302212 audio_extn_keep_alive_start();
2213
Naresh Tanniru85819452017-05-04 18:55:45 -07002214 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2215 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2216 if (ret < 0)
2217 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2218 }
2219
Eric Laurent994a6932013-07-17 11:51:42 -07002220 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 return ret;
2222}
2223
2224int start_output_stream(struct stream_out *out)
2225{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 struct audio_usecase *uc_info;
2228 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002229 char mixer_ctl_name[128];
2230 struct mixer_ctl *ctl = NULL;
2231 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002233 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2234 ret = -EINVAL;
2235 goto error_config;
2236 }
2237
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302238 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2239 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2240 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302241
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302242 if (CARD_STATUS_OFFLINE == out->card_status ||
2243 CARD_STATUS_OFFLINE == adev->card_status) {
2244 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302245 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302246 goto error_config;
2247 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302248
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302249 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2250 if (!audio_extn_a2dp_is_ready()) {
2251 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2252 //combo usecase just by pass a2dp
2253 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2254 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2255 } else {
2256 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2257 ret = -EAGAIN;
2258 goto error_config;
2259 }
2260 }
2261 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002262 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 if (out->pcm_device_id < 0) {
2264 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2265 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002266 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002267 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 }
2269
2270 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002271
2272 if (!uc_info) {
2273 ret = -ENOMEM;
2274 goto error_config;
2275 }
2276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 uc_info->id = out->usecase;
2278 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002279 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 uc_info->devices = out->devices;
2281 uc_info->in_snd_device = SND_DEVICE_NONE;
2282 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002283 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302285 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2286 adev->perf_lock_opts,
2287 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302288
2289 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2290 audio_extn_keep_alive_stop();
2291 if (audio_extn_passthru_is_enabled() &&
2292 audio_extn_passthru_is_passthrough_stream(out)) {
2293 audio_extn_passthru_on_start(out);
2294 audio_extn_passthru_update_stream_configuration(adev, out);
2295 }
2296 }
2297
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002298 select_devices(adev, out->usecase);
2299
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002300 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2301 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002302 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002303 unsigned int flags = PCM_OUT;
2304 unsigned int pcm_open_retry_count = 0;
2305 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2306 flags |= PCM_MMAP | PCM_NOIRQ;
2307 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002308 } else if (out->realtime) {
2309 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002310 } else
2311 flags |= PCM_MONOTONIC;
2312
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002313 if ((adev->vr_audio_mode_enabled) &&
2314 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2315 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2316 "PCM_Dev %d Topology", out->pcm_device_id);
2317 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2318 if (!ctl) {
2319 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2320 __func__, mixer_ctl_name);
2321 } else {
2322 //if success use ULLPP
2323 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2324 __func__, mixer_ctl_name, out->pcm_device_id);
2325 //There is a still a possibility that some sessions
2326 // that request for FAST|RAW when 3D audio is active
2327 //can go through ULLPP. Ideally we expects apps to
2328 //listen to audio focus and stop concurrent playback
2329 //Also, we will look for mode flag (voice_in_communication)
2330 //before enabling the realtime flag.
2331 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2332 }
2333 }
2334
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002335 while (1) {
2336 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2337 flags, &out->config);
2338 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2339 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2340 if (out->pcm != NULL) {
2341 pcm_close(out->pcm);
2342 out->pcm = NULL;
2343 }
2344 if (pcm_open_retry_count-- == 0) {
2345 ret = -EIO;
2346 goto error_open;
2347 }
2348 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2349 continue;
2350 }
2351 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002353
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002354 ALOGV("%s: pcm_prepare", __func__);
2355 if (pcm_is_ready(out->pcm)) {
2356 ret = pcm_prepare(out->pcm);
2357 if (ret < 0) {
2358 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2359 pcm_close(out->pcm);
2360 out->pcm = NULL;
2361 goto error_open;
2362 }
2363 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302364 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302365 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002368 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302369 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002371 out->compr = compress_open(adev->snd_card,
2372 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 COMPRESS_IN, &out->compr_config);
2374 if (out->compr && !is_compress_ready(out->compr)) {
2375 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2376 compress_close(out->compr);
2377 out->compr = NULL;
2378 ret = -EIO;
2379 goto error_open;
2380 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302381 /* compress_open sends params of the track, so reset the flag here */
2382 out->is_compr_metadata_avail = false;
2383
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002384 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002386
Fred Oh3f43e742015-03-04 18:42:34 -08002387 /* Since small bufs uses blocking writes, a write will be blocked
2388 for the default max poll time (20s) in the event of an SSR.
2389 Reduce the poll time to observe and deal with SSR faster.
2390 */
Ashish Jain5106d362016-05-11 19:23:33 +05302391 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002392 compress_set_max_poll_wait(out->compr, 1000);
2393 }
2394
Manish Dewangan69426c82017-01-30 17:35:36 +05302395 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302396 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302397
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002398 audio_extn_dts_create_state_notifier_node(out->usecase);
2399 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2400 popcount(out->channel_mask),
2401 out->playback_started);
2402
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002403#ifdef DS1_DOLBY_DDP_ENABLED
2404 if (audio_extn_is_dolby_format(out->format))
2405 audio_extn_dolby_send_ddp_endp_params(adev);
2406#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302407 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2408 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002409 if (adev->visualizer_start_output != NULL)
2410 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2411 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302412 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002413 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002416
2417 if (ret == 0) {
2418 register_out_stream(out);
2419 if (out->realtime) {
2420 ret = pcm_start(out->pcm);
2421 if (ret < 0)
2422 goto error_open;
2423 }
2424 }
2425
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302426 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002427 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002428
Naresh Tanniru85819452017-05-04 18:55:45 -07002429 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2430 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out);
2431 if (ret < 0)
2432 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2433 }
2434
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002435 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302437 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002439error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302440 /*
2441 * sleep 50ms to allow sufficient time for kernel
2442 * drivers to recover incases like SSR.
2443 */
2444 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002445 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446}
2447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448static int check_input_parameters(uint32_t sample_rate,
2449 audio_format_t format,
2450 int channel_count)
2451{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002452 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302454 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2455 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2456 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002457 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302458 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002459
2460 switch (channel_count) {
2461 case 1:
2462 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302463 case 3:
2464 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002465 case 6:
2466 break;
2467 default:
2468 ret = -EINVAL;
2469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470
2471 switch (sample_rate) {
2472 case 8000:
2473 case 11025:
2474 case 12000:
2475 case 16000:
2476 case 22050:
2477 case 24000:
2478 case 32000:
2479 case 44100:
2480 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302481 case 96000:
2482 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 break;
2484 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002485 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 }
2487
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002488 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489}
2490
2491static size_t get_input_buffer_size(uint32_t sample_rate,
2492 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002493 int channel_count,
2494 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495{
2496 size_t size = 0;
2497
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002498 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2499 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002501 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002502 if (is_low_latency)
2503 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302504
2505 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002507 /* make sure the size is multiple of 32 bytes
2508 * At 48 kHz mono 16-bit PCM:
2509 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2510 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2511 */
2512 size += 0x1f;
2513 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002514
2515 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516}
2517
Ashish Jain058165c2016-09-28 23:18:48 +05302518static size_t get_output_period_size(uint32_t sample_rate,
2519 audio_format_t format,
2520 int channel_count,
2521 int duration /*in millisecs*/)
2522{
2523 size_t size = 0;
2524 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2525
2526 if ((duration == 0) || (sample_rate == 0) ||
2527 (bytes_per_sample == 0) || (channel_count == 0)) {
2528 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2529 bytes_per_sample, channel_count);
2530 return -EINVAL;
2531 }
2532
2533 size = (sample_rate *
2534 duration *
2535 bytes_per_sample *
2536 channel_count) / 1000;
2537 /*
2538 * To have same PCM samples for all channels, the buffer size requires to
2539 * be multiple of (number of channels * bytes per sample)
2540 * For writes to succeed, the buffer must be written at address which is multiple of 32
2541 */
2542 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2543
2544 return (size/(channel_count * bytes_per_sample));
2545}
2546
Ashish Jain5106d362016-05-11 19:23:33 +05302547static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2548{
2549 uint64_t actual_frames_rendered = 0;
2550 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2551
2552 /* This adjustment accounts for buffering after app processor.
2553 * It is based on estimated DSP latency per use case, rather than exact.
2554 */
2555 int64_t platform_latency = platform_render_latency(out->usecase) *
2556 out->sample_rate / 1000000LL;
2557
2558 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2559 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2560 * hence only estimate.
2561 */
2562 int64_t signed_frames = out->written - kernel_buffer_size;
2563
2564 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2565
2566 if (signed_frames > 0)
2567 actual_frames_rendered = signed_frames;
2568
2569 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2570 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2571 (long long int)out->written, (int)kernel_buffer_size,
2572 audio_bytes_per_sample(out->compr_config.codec->format),
2573 popcount(out->channel_mask));
2574
2575 return actual_frames_rendered;
2576}
2577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2579{
2580 struct stream_out *out = (struct stream_out *)stream;
2581
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583}
2584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002585static int out_set_sample_rate(struct audio_stream *stream __unused,
2586 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return -ENOSYS;
2589}
2590
2591static size_t out_get_buffer_size(const struct audio_stream *stream)
2592{
2593 struct stream_out *out = (struct stream_out *)stream;
2594
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302595 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2596 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2597 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2598 else
2599 return out->compr_config.fragment_size;
2600 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002601 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302602 else if (is_offload_usecase(out->usecase) &&
2603 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302604 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002605
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002606 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002607 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608}
2609
2610static uint32_t out_get_channels(const struct audio_stream *stream)
2611{
2612 struct stream_out *out = (struct stream_out *)stream;
2613
2614 return out->channel_mask;
2615}
2616
2617static audio_format_t out_get_format(const struct audio_stream *stream)
2618{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002619 struct stream_out *out = (struct stream_out *)stream;
2620
2621 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622}
2623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002624static int out_set_format(struct audio_stream *stream __unused,
2625 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626{
2627 return -ENOSYS;
2628}
2629
2630static int out_standby(struct audio_stream *stream)
2631{
2632 struct stream_out *out = (struct stream_out *)stream;
2633 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302635 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2636 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002638 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002640 if (adev->adm_deregister_stream)
2641 adev->adm_deregister_stream(adev->adm_data, out->handle);
2642
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002643 if (is_offload_usecase(out->usecase))
2644 stop_compressed_output_l(out);
2645
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002646 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002648 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2649 voice_extn_compress_voip_close_output_stream(stream);
2650 pthread_mutex_unlock(&adev->lock);
2651 pthread_mutex_unlock(&out->lock);
2652 ALOGD("VOIP output entered standby");
2653 return 0;
2654 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655 if (out->pcm) {
2656 pcm_close(out->pcm);
2657 out->pcm = NULL;
2658 }
2659 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002660 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302661 out->send_next_track_params = false;
2662 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002663 out->gapless_mdata.encoder_delay = 0;
2664 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002665 if (out->compr != NULL) {
2666 compress_close(out->compr);
2667 out->compr = NULL;
2668 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002671 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 }
2673 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302674 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 return 0;
2676}
2677
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302678static int out_on_error(struct audio_stream *stream)
2679{
2680 struct stream_out *out = (struct stream_out *)stream;
2681 bool do_standby = false;
2682
2683 lock_output_stream(out);
2684 if (!out->standby) {
2685 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2686 stop_compressed_output_l(out);
2687 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2688 } else
2689 do_standby = true;
2690 }
2691 pthread_mutex_unlock(&out->lock);
2692
2693 if (do_standby)
2694 return out_standby(&out->stream.common);
2695
2696 return 0;
2697}
2698
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002699static int out_dump(const struct audio_stream *stream __unused,
2700 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701{
2702 return 0;
2703}
2704
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002705static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2706{
2707 int ret = 0;
2708 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002709
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002710 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002711 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002712 return -EINVAL;
2713 }
2714
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302715 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002716
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002717 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2718 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302719 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002720 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002721 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2722 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302723 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002724 }
2725
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002726 ALOGV("%s new encoder delay %u and padding %u", __func__,
2727 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2728
2729 return 0;
2730}
2731
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002732static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2733{
2734 return out == adev->primary_output || out == adev->voice_tx_output;
2735}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002736
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302737// note: this call is safe only if the stream_cb is
2738// removed first in close_output_stream (as is done now).
2739static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2740{
2741 if (!stream || !parms)
2742 return;
2743
2744 struct stream_out *out = (struct stream_out *)stream;
2745 struct audio_device *adev = out->dev;
2746
2747 card_status_t status;
2748 int card;
2749 if (parse_snd_card_status(parms, &card, &status) < 0)
2750 return;
2751
2752 pthread_mutex_lock(&adev->lock);
2753 bool valid_cb = (card == adev->snd_card);
2754 pthread_mutex_unlock(&adev->lock);
2755
2756 if (!valid_cb)
2757 return;
2758
2759 lock_output_stream(out);
2760 if (out->card_status != status)
2761 out->card_status = status;
2762 pthread_mutex_unlock(&out->lock);
2763
2764 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
2765 use_case_table[out->usecase],
2766 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2767
2768 if (status == CARD_STATUS_OFFLINE)
2769 out_on_error(stream);
2770
2771 return;
2772}
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2775{
2776 struct stream_out *out = (struct stream_out *)stream;
2777 struct audio_device *adev = out->dev;
2778 struct str_parms *parms;
2779 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002780 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781
sangwoobc677242013-08-08 16:53:43 +09002782 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002783 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302785 if (!parms)
2786 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002787 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2788 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002790 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002791 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002793 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002794 * When HDMI cable is unplugged the music playback is paused and
2795 * the policy manager sends routing=0. But the audioflinger continues
2796 * to write data until standby time (3sec). As the HDMI core is
2797 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002798 * Avoid this by routing audio to speaker until standby.
2799 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002800 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2801 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302802 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002803 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2804 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002805 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302806 /*
2807 * When A2DP is disconnected the
2808 * music playback is paused and the policy manager sends routing=0
2809 * But the audioflingercontinues to write data until standby time
2810 * (3sec). As BT is turned off, the write gets blocked.
2811 * Avoid this by routing audio to speaker until standby.
2812 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002813 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302814 (val == AUDIO_DEVICE_NONE)) {
2815 val = AUDIO_DEVICE_OUT_SPEAKER;
2816 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302817 /* To avoid a2dp to sco overlapping / BT device improper state
2818 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302819 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302820 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2821 if (!audio_extn_a2dp_is_ready()) {
2822 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2823 //combo usecase just by pass a2dp
2824 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2825 val = AUDIO_DEVICE_OUT_SPEAKER;
2826 } else {
2827 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2828 /* update device to a2dp and don't route as BT returned error
2829 * However it is still possible a2dp routing called because
2830 * of current active device disconnection (like wired headset)
2831 */
2832 out->devices = val;
2833 pthread_mutex_unlock(&out->lock);
2834 pthread_mutex_unlock(&adev->lock);
2835 goto error;
2836 }
2837 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002839 /*
2840 * select_devices() call below switches all the usecases on the same
2841 * backend to the new device. Refer to check_usecases_codec_backend() in
2842 * the select_devices(). But how do we undo this?
2843 *
2844 * For example, music playback is active on headset (deep-buffer usecase)
2845 * and if we go to ringtones and select a ringtone, low-latency usecase
2846 * will be started on headset+speaker. As we can't enable headset+speaker
2847 * and headset devices at the same time, select_devices() switches the music
2848 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2849 * So when the ringtone playback is completed, how do we undo the same?
2850 *
2851 * We are relying on the out_set_parameters() call on deep-buffer output,
2852 * once the ringtone playback is ended.
2853 * NOTE: We should not check if the current devices are same as new devices.
2854 * Because select_devices() must be called to switch back the music
2855 * playback to headset.
2856 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002857 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002858 audio_devices_t new_dev = val;
2859 bool same_dev = out->devices == new_dev;
2860 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002861
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002862 if (output_drives_call(adev, out)) {
2863 if(!voice_is_in_call(adev)) {
2864 if (adev->mode == AUDIO_MODE_IN_CALL) {
2865 adev->current_call_output = out;
2866 ret = voice_start_call(adev);
2867 }
2868 } else {
2869 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002870 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002871 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002872 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002873
2874 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002875 if (!same_dev) {
2876 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302877 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2878 adev->perf_lock_opts,
2879 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002880 if (adev->adm_on_routing_change)
2881 adev->adm_on_routing_change(adev->adm_data,
2882 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002883 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002884 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302885 if (!same_dev)
2886 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002887 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002888 }
2889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002891 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002893
2894 if (out == adev->primary_output) {
2895 pthread_mutex_lock(&adev->lock);
2896 audio_extn_set_parameters(adev, parms);
2897 pthread_mutex_unlock(&adev->lock);
2898 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002899 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002900 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002901 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002902
2903 audio_extn_dts_create_state_notifier_node(out->usecase);
2904 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2905 popcount(out->channel_mask),
2906 out->playback_started);
2907
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002908 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002909 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002910
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302911 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2912 if (err >= 0) {
2913 strlcpy(out->profile, value, sizeof(out->profile));
2914 ALOGV("updating stream profile with value '%s'", out->profile);
2915 lock_output_stream(out);
2916 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2917 &adev->streams_output_cfg_list,
2918 out->devices, out->flags, out->format,
2919 out->sample_rate, out->bit_width,
2920 out->channel_mask, out->profile,
2921 &out->app_type_cfg);
2922 pthread_mutex_unlock(&out->lock);
2923 }
2924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302926error:
Eric Laurent994a6932013-07-17 11:51:42 -07002927 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 return ret;
2929}
2930
2931static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2932{
2933 struct stream_out *out = (struct stream_out *)stream;
2934 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002935 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 char value[256];
2937 struct str_parms *reply = str_parms_create();
2938 size_t i, j;
2939 int ret;
2940 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002941
2942 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002943 if (reply) {
2944 str_parms_destroy(reply);
2945 }
2946 if (query) {
2947 str_parms_destroy(query);
2948 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002949 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2950 return NULL;
2951 }
2952
Eric Laurent994a6932013-07-17 11:51:42 -07002953 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2955 if (ret >= 0) {
2956 value[0] = '\0';
2957 i = 0;
2958 while (out->supported_channel_masks[i] != 0) {
2959 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2960 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2961 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002962 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002964 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 first = false;
2966 break;
2967 }
2968 }
2969 i++;
2970 }
2971 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2972 str = str_parms_to_str(reply);
2973 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002974 voice_extn_out_get_parameters(out, query, reply);
2975 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002976 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002977 free(str);
2978 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002981
Alexy Joseph62142aa2015-11-16 15:10:34 -08002982
2983 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2984 if (ret >= 0) {
2985 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302986 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2987 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002988 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302989 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002990 } else {
2991 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302992 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002993 }
2994 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002995 if (str)
2996 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002997 str = str_parms_to_str(reply);
2998 }
2999
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003000 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3001 if (ret >= 0) {
3002 value[0] = '\0';
3003 i = 0;
3004 first = true;
3005 while (out->supported_formats[i] != 0) {
3006 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3007 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3008 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003009 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003010 }
3011 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3012 first = false;
3013 break;
3014 }
3015 }
3016 i++;
3017 }
3018 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003019 if (str)
3020 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003021 str = str_parms_to_str(reply);
3022 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003023
3024 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3025 if (ret >= 0) {
3026 value[0] = '\0';
3027 i = 0;
3028 first = true;
3029 while (out->supported_sample_rates[i] != 0) {
3030 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3031 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3032 if (!first) {
3033 strlcat(value, "|", sizeof(value));
3034 }
3035 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3036 first = false;
3037 break;
3038 }
3039 }
3040 i++;
3041 }
3042 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3043 if (str)
3044 free(str);
3045 str = str_parms_to_str(reply);
3046 }
3047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 str_parms_destroy(query);
3049 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003050 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 return str;
3052}
3053
3054static uint32_t out_get_latency(const struct audio_stream_out *stream)
3055{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003056 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003058 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059
Alexy Josephaa54c872014-12-03 02:46:47 -08003060 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303061 lock_output_stream(out);
3062 latency = audio_extn_utils_compress_get_dsp_latency(out);
3063 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003064 } else if (out->realtime) {
3065 // since the buffer won't be filled up faster than realtime,
3066 // return a smaller number
3067 if (out->config.rate)
3068 period_ms = (out->af_period_multiplier * out->config.period_size *
3069 1000) / (out->config.rate);
3070 else
3071 period_ms = 0;
3072 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003073 } else {
3074 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003075 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003076 }
3077
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003078 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3079 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3080 latency += audio_extn_a2dp_get_encoder_latency();
3081
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303082 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003083 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303086static float AmpToDb(float amplification)
3087{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303088 float db = DSD_VOLUME_MIN_DB;
3089 if (amplification > 0) {
3090 db = 20 * log10(amplification);
3091 if(db < DSD_VOLUME_MIN_DB)
3092 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303093 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303094 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303095}
3096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097static int out_set_volume(struct audio_stream_out *stream, float left,
3098 float right)
3099{
Eric Laurenta9024de2013-04-04 09:19:12 -07003100 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003101 int volume[2];
3102
Eric Laurenta9024de2013-04-04 09:19:12 -07003103 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3104 /* only take left channel into account: the API is for stereo anyway */
3105 out->muted = (left == 0.0f);
3106 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003107 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303108 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003109 /*
3110 * Set mute or umute on HDMI passthrough stream.
3111 * Only take left channel into account.
3112 * Mute is 0 and unmute 1
3113 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303114 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303115 } else if (out->format == AUDIO_FORMAT_DSD){
3116 char mixer_ctl_name[128] = "DSD Volume";
3117 struct audio_device *adev = out->dev;
3118 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3119
3120 if (!ctl) {
3121 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3122 __func__, mixer_ctl_name);
3123 return -EINVAL;
3124 }
3125 volume[0] = (int)(AmpToDb(left));
3126 volume[1] = (int)(AmpToDb(right));
3127 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3128 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003129 } else {
3130 char mixer_ctl_name[128];
3131 struct audio_device *adev = out->dev;
3132 struct mixer_ctl *ctl;
3133 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003134 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003136 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3137 "Compress Playback %d Volume", pcm_device_id);
3138 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3139 if (!ctl) {
3140 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3141 __func__, mixer_ctl_name);
3142 return -EINVAL;
3143 }
3144 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3145 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3146 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3147 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003149 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 return -ENOSYS;
3152}
3153
3154static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3155 size_t bytes)
3156{
3157 struct stream_out *out = (struct stream_out *)stream;
3158 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003159 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003161 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303163 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003164
Dhananjay Kumarac341582017-02-23 23:42:25 +05303165 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303166 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303167 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3168 pthread_mutex_unlock(&out->lock);
3169 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303170 } else {
3171 /* increase written size during SSR to avoid mismatch
3172 * with the written frames count in AF
3173 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003174 // bytes per frame
3175 size_t bpf = audio_bytes_per_sample(out->format) *
3176 audio_channel_count_from_out_mask(out->channel_mask);
3177 if (bpf != 0)
3178 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303179 ALOGD(" %s: sound card is not active/SSR state", __func__);
3180 ret= -EIO;
3181 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303182 }
3183 }
3184
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303185 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303186 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3187 if (audio_bytes_per_sample(out->format) != 0)
3188 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3189 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303190 goto exit;
3191 }
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003194 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003195 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003196 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3197 ret = voice_extn_compress_voip_start_output_stream(out);
3198 else
3199 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003200 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003203 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 goto exit;
3205 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003206
3207 if (last_known_cal_step != -1) {
3208 ALOGD("%s: retry previous failed cal level set", __func__);
3209 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
Ashish Jain81eb2a82015-05-13 10:52:34 +05303213 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003214 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303215 adev->is_channel_status_set = true;
3216 }
3217
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003218 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003219 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003220 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003221 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003222 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3223 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303224 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3225 ALOGD("copl(%p):send next track params in gapless", out);
3226 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3227 out->send_next_track_params = false;
3228 out->is_compr_metadata_avail = false;
3229 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003230 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303231 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303232 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003233
Ashish Jain83a6cc22016-06-28 14:34:17 +05303234 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303235 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303236 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303237 pthread_mutex_unlock(&out->lock);
3238 return -EINVAL;
3239 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303240 audio_format_t dst_format = out->hal_op_format;
3241 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303242
3243 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3244 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3245
Ashish Jain83a6cc22016-06-28 14:34:17 +05303246 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303247 dst_format,
3248 buffer,
3249 src_format,
3250 frames);
3251
Ashish Jain83a6cc22016-06-28 14:34:17 +05303252 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303253 bytes_to_write);
3254
3255 /*Convert written bytes in audio flinger format*/
3256 if (ret > 0)
3257 ret = ((ret * format_to_bitwidth_table[out->format]) /
3258 format_to_bitwidth_table[dst_format]);
3259 }
3260 } else
3261 ret = compress_write(out->compr, buffer, bytes);
3262
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303263 if (ret < 0)
3264 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303265 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303266 /*msg to cb thread only if non blocking write is enabled*/
3267 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303268 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303270 } else if (-ENETRESET == ret) {
3271 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303272 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303273 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303274 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 }
Ashish Jain5106d362016-05-11 19:23:33 +05303276 if ( ret == (ssize_t)bytes && !out->non_blocking)
3277 out->written += bytes;
3278
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303279 /* Call compr start only when non-zero bytes of data is there to be rendered */
3280 if (!out->playback_started && ret > 0) {
3281 int status = compress_start(out->compr);
3282 if (status < 0) {
3283 ret = status;
3284 ALOGE("%s: compr start failed with err %d", __func__, errno);
3285 goto exit;
3286 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003287 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 out->playback_started = 1;
3289 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003290
3291 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3292 popcount(out->channel_mask),
3293 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 }
3295 pthread_mutex_unlock(&out->lock);
3296 return ret;
3297 } else {
3298 if (out->pcm) {
3299 if (out->muted)
3300 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003301
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303302 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003303
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003304 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003305
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003306 if (out->config.rate)
3307 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3308 out->config.rate;
3309
3310 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3311
3312 request_out_focus(out, ns);
3313
3314 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003315 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003316 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303317 out->convert_buffer != NULL) {
3318
3319 memcpy_by_audio_format(out->convert_buffer,
3320 out->hal_op_format,
3321 buffer,
3322 out->hal_ip_format,
3323 out->config.period_size * out->config.channels);
3324
3325 ret = pcm_write(out->pcm, out->convert_buffer,
3326 (out->config.period_size *
3327 out->config.channels *
3328 format_to_bitwidth_table[out->hal_op_format]));
3329 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303330 /*
3331 * To avoid underrun in DSP when the application is not pumping
3332 * data at required rate, check for the no. of bytes and ignore
3333 * pcm_write if it is less than actual buffer size.
3334 * It is a work around to a change in compress VOIP driver.
3335 */
3336 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3337 bytes < (out->config.period_size * out->config.channels *
3338 audio_bytes_per_sample(out->format))) {
3339 size_t voip_buf_size =
3340 out->config.period_size * out->config.channels *
3341 audio_bytes_per_sample(out->format);
3342 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3343 __func__, bytes, voip_buf_size);
3344 usleep(((uint64_t)voip_buf_size - bytes) *
3345 1000000 / audio_stream_out_frame_size(stream) /
3346 out_get_sample_rate(&out->stream.common));
3347 ret = 0;
3348 } else
3349 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303350 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003352 release_out_focus(out);
3353
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303354 if (ret < 0)
3355 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303356 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3357 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3358 else
3359 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 }
3362
3363exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303364 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303365 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303366 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 pthread_mutex_unlock(&out->lock);
3368
3369 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003370 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003371 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303372 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303373 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303374 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303375 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303376 out->standby = true;
3377 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303378 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303379 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3380 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3381 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 }
3383 return bytes;
3384}
3385
3386static int out_get_render_position(const struct audio_stream_out *stream,
3387 uint32_t *dsp_frames)
3388{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003390
3391 if (dsp_frames == NULL)
3392 return -EINVAL;
3393
3394 *dsp_frames = 0;
3395 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003396 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303397
3398 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3399 * this operation and adev_close_output_stream(where out gets reset).
3400 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303401 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303402 *dsp_frames = get_actual_pcm_frames_rendered(out);
3403 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3404 return 0;
3405 }
3406
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003407 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303408 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303409 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003410 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303411 if (ret < 0)
3412 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303414 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303416 if (-ENETRESET == ret) {
3417 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303418 out->card_status = CARD_STATUS_OFFLINE;
3419 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303420 } else if(ret < 0) {
3421 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303422 ret = -EINVAL;
3423 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303424 /*
3425 * Handle corner case where compress session is closed during SSR
3426 * and timestamp is queried
3427 */
3428 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303429 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303430 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303431 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303432 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303433 pthread_mutex_unlock(&out->lock);
3434 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003435 } else if (audio_is_linear_pcm(out->format)) {
3436 *dsp_frames = out->written;
3437 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003438 } else
3439 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440}
3441
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003442static int out_add_audio_effect(const struct audio_stream *stream __unused,
3443 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444{
3445 return 0;
3446}
3447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003448static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3449 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450{
3451 return 0;
3452}
3453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003454static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3455 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456{
3457 return -EINVAL;
3458}
3459
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003460static int out_get_presentation_position(const struct audio_stream_out *stream,
3461 uint64_t *frames, struct timespec *timestamp)
3462{
3463 struct stream_out *out = (struct stream_out *)stream;
3464 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003465 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003466
Ashish Jain5106d362016-05-11 19:23:33 +05303467 /* below piece of code is not guarded against any lock because audioFliner serializes
3468 * this operation and adev_close_output_stream( where out gets reset).
3469 */
3470 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303471 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303472 *frames = get_actual_pcm_frames_rendered(out);
3473 /* this is the best we can do */
3474 clock_gettime(CLOCK_MONOTONIC, timestamp);
3475 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3476 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3477 return 0;
3478 }
3479
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003480 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003481
Ashish Jain5106d362016-05-11 19:23:33 +05303482 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3483 ret = compress_get_tstamp(out->compr, &dsp_frames,
3484 &out->sample_rate);
3485 ALOGVV("%s rendered frames %ld sample_rate %d",
3486 __func__, dsp_frames, out->sample_rate);
3487 *frames = dsp_frames;
3488 if (ret < 0)
3489 ret = -errno;
3490 if (-ENETRESET == ret) {
3491 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303492 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303493 ret = -EINVAL;
3494 } else
3495 ret = 0;
3496 /* this is the best we can do */
3497 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003498 } else {
3499 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003500 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003501 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3502 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003503 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003504 // This adjustment accounts for buffering after app processor.
3505 // It is based on estimated DSP latency per use case, rather than exact.
3506 signed_frames -=
3507 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3508
Eric Laurent949a0892013-09-20 09:20:13 -07003509 // It would be unusual for this value to be negative, but check just in case ...
3510 if (signed_frames >= 0) {
3511 *frames = signed_frames;
3512 ret = 0;
3513 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003514 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303515 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303516 *frames = out->written;
3517 clock_gettime(CLOCK_MONOTONIC, timestamp);
3518 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003519 }
3520 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003521 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003522 return ret;
3523}
3524
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525static int out_set_callback(struct audio_stream_out *stream,
3526 stream_callback_t callback, void *cookie)
3527{
3528 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003529 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530
3531 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003532 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003533 out->client_callback = callback;
3534 out->client_cookie = cookie;
3535 if (out->adsp_hdlr_stream_handle) {
3536 ret = audio_extn_adsp_hdlr_stream_set_callback(
3537 out->adsp_hdlr_stream_handle,
3538 callback,
3539 cookie);
3540 if (ret)
3541 ALOGW("%s:adsp hdlr callback registration failed %d",
3542 __func__, ret);
3543 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544 pthread_mutex_unlock(&out->lock);
3545 return 0;
3546}
3547
3548static int out_pause(struct audio_stream_out* stream)
3549{
3550 struct stream_out *out = (struct stream_out *)stream;
3551 int status = -ENOSYS;
3552 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003553 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003554 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003555 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003556 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303557 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303558 status = compress_pause(out->compr);
3559
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003561
Mingming Yin21854652016-04-13 11:54:02 -07003562 if (audio_extn_passthru_is_active()) {
3563 ALOGV("offload use case, pause passthru");
3564 audio_extn_passthru_on_pause(out);
3565 }
3566
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303567 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003568 audio_extn_dts_notify_playback_state(out->usecase, 0,
3569 out->sample_rate, popcount(out->channel_mask),
3570 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003571 }
3572 pthread_mutex_unlock(&out->lock);
3573 }
3574 return status;
3575}
3576
3577static int out_resume(struct audio_stream_out* stream)
3578{
3579 struct stream_out *out = (struct stream_out *)stream;
3580 int status = -ENOSYS;
3581 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003582 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003583 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003585 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303587 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303588 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003589 }
3590 if (!status) {
3591 out->offload_state = OFFLOAD_STATE_PLAYING;
3592 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303593 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003594 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3595 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 }
3597 pthread_mutex_unlock(&out->lock);
3598 }
3599 return status;
3600}
3601
3602static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3603{
3604 struct stream_out *out = (struct stream_out *)stream;
3605 int status = -ENOSYS;
3606 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003607 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003608 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3610 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3611 else
3612 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3613 pthread_mutex_unlock(&out->lock);
3614 }
3615 return status;
3616}
3617
3618static int out_flush(struct audio_stream_out* stream)
3619{
3620 struct stream_out *out = (struct stream_out *)stream;
3621 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003622 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003623 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003624 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003625 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3626 stop_compressed_output_l(out);
3627 out->written = 0;
3628 } else {
3629 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3630 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003631 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003632 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 return 0;
3634 }
3635 return -ENOSYS;
3636}
3637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638/** audio_stream_in implementation **/
3639static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3640{
3641 struct stream_in *in = (struct stream_in *)stream;
3642
3643 return in->config.rate;
3644}
3645
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003646static int in_set_sample_rate(struct audio_stream *stream __unused,
3647 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648{
3649 return -ENOSYS;
3650}
3651
3652static size_t in_get_buffer_size(const struct audio_stream *stream)
3653{
3654 struct stream_in *in = (struct stream_in *)stream;
3655
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003656 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3657 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003658 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3659 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303660 else if(audio_extn_cin_attached_usecase(in->usecase))
3661 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003662
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003663 return in->config.period_size * in->af_period_multiplier *
3664 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665}
3666
3667static uint32_t in_get_channels(const struct audio_stream *stream)
3668{
3669 struct stream_in *in = (struct stream_in *)stream;
3670
3671 return in->channel_mask;
3672}
3673
3674static audio_format_t in_get_format(const struct audio_stream *stream)
3675{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003676 struct stream_in *in = (struct stream_in *)stream;
3677
3678 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679}
3680
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003681static int in_set_format(struct audio_stream *stream __unused,
3682 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683{
3684 return -ENOSYS;
3685}
3686
3687static int in_standby(struct audio_stream *stream)
3688{
3689 struct stream_in *in = (struct stream_in *)stream;
3690 struct audio_device *adev = in->dev;
3691 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303692 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3693 stream, in->usecase, use_case_table[in->usecase]);
3694
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003695 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003696 if (!in->standby && in->is_st_session) {
3697 ALOGD("%s: sound trigger pcm stop lab", __func__);
3698 audio_extn_sound_trigger_stop_lab(in);
3699 in->standby = 1;
3700 }
3701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003703 if (adev->adm_deregister_stream)
3704 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3705
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003706 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003708 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3709 voice_extn_compress_voip_close_input_stream(stream);
3710 ALOGD("VOIP input entered standby");
3711 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303712 if (audio_extn_cin_attached_usecase(in->usecase))
3713 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003714 if (in->pcm) {
3715 pcm_close(in->pcm);
3716 in->pcm = NULL;
3717 }
3718 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003719 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003720 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 }
3722 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003723 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 return status;
3725}
3726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003727static int in_dump(const struct audio_stream *stream __unused,
3728 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729{
3730 return 0;
3731}
3732
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303733static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3734{
3735 if (!stream || !parms)
3736 return;
3737
3738 struct stream_in *in = (struct stream_in *)stream;
3739 struct audio_device *adev = in->dev;
3740
3741 card_status_t status;
3742 int card;
3743 if (parse_snd_card_status(parms, &card, &status) < 0)
3744 return;
3745
3746 pthread_mutex_lock(&adev->lock);
3747 bool valid_cb = (card == adev->snd_card);
3748 pthread_mutex_unlock(&adev->lock);
3749
3750 if (!valid_cb)
3751 return;
3752
3753 lock_input_stream(in);
3754 if (in->card_status != status)
3755 in->card_status = status;
3756 pthread_mutex_unlock(&in->lock);
3757
3758 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3759 use_case_table[in->usecase],
3760 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3761
3762 // a better solution would be to report error back to AF and let
3763 // it put the stream to standby
3764 if (status == CARD_STATUS_OFFLINE)
3765 in_standby(&in->stream.common);
3766
3767 return;
3768}
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3771{
3772 struct stream_in *in = (struct stream_in *)stream;
3773 struct audio_device *adev = in->dev;
3774 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003776 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303778 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 parms = str_parms_create_str(kvpairs);
3780
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303781 if (!parms)
3782 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003783 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003784 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003785
3786 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3787 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 val = atoi(value);
3789 /* no audio source uses val == 0 */
3790 if ((in->source != val) && (val != 0)) {
3791 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003792 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3793 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3794 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003795 (in->config.rate == 8000 || in->config.rate == 16000 ||
3796 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003797 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003798 err = voice_extn_compress_voip_open_input_stream(in);
3799 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003800 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003801 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003802 }
3803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 }
3805 }
3806
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003807 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3808 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003810 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 in->device = val;
3812 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003813 if (!in->standby && !in->is_st_session) {
3814 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003815 if (adev->adm_on_routing_change)
3816 adev->adm_on_routing_change(adev->adm_data,
3817 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003818 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 }
3821 }
3822
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303823 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3824 if (err >= 0) {
3825 strlcpy(in->profile, value, sizeof(in->profile));
3826 ALOGV("updating stream profile with value '%s'", in->profile);
3827 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3828 &adev->streams_input_cfg_list,
3829 in->device, in->flags, in->format,
3830 in->sample_rate, in->bit_width,
3831 in->profile, &in->app_type_cfg);
3832 }
3833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003835 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836
3837 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303838error:
Eric Laurent994a6932013-07-17 11:51:42 -07003839 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 return ret;
3841}
3842
3843static char* in_get_parameters(const struct audio_stream *stream,
3844 const char *keys)
3845{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003846 struct stream_in *in = (struct stream_in *)stream;
3847 struct str_parms *query = str_parms_create_str(keys);
3848 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003849 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003850
3851 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("in_get_parameters: failed to create query or reply");
3859 return NULL;
3860 }
3861
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003862 ALOGV("%s: enter: keys - %s", __func__, keys);
3863
3864 voice_extn_in_get_parameters(in, query, reply);
3865
3866 str = str_parms_to_str(reply);
3867 str_parms_destroy(query);
3868 str_parms_destroy(reply);
3869
3870 ALOGV("%s: exit: returns - %s", __func__, str);
3871 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872}
3873
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003874static int in_set_gain(struct audio_stream_in *stream __unused,
3875 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876{
3877 return 0;
3878}
3879
3880static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3881 size_t bytes)
3882{
3883 struct stream_in *in = (struct stream_in *)stream;
3884 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303885 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303886 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003888 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303889
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003890 if (in->is_st_session) {
3891 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3892 /* Read from sound trigger HAL */
3893 audio_extn_sound_trigger_read(in, buffer, bytes);
3894 pthread_mutex_unlock(&in->lock);
3895 return bytes;
3896 }
3897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003899 pthread_mutex_lock(&adev->lock);
3900 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3901 ret = voice_extn_compress_voip_start_input_stream(in);
3902 else
3903 ret = start_input_stream(in);
3904 pthread_mutex_unlock(&adev->lock);
3905 if (ret != 0) {
3906 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 }
3908 in->standby = 0;
3909 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003911 // what's the duration requested by the client?
3912 long ns = 0;
3913
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303914 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003915 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3916 in->config.rate;
3917
3918 request_in_focus(in, ns);
3919 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003920
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303921 if (audio_extn_cin_attached_usecase(in->usecase)) {
3922 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3923 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303924 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003925 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303926 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003927 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003928 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003929 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303930 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003931 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303932 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3933 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3934 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3935 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303936 ret = -EINVAL;
3937 goto exit;
3938 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303939 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303940 ret = -errno;
3941 }
3942 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303943 /* bytes read is always set to bytes for non compress usecases */
3944 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945 }
3946
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003947 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 /*
3950 * Instead of writing zeroes here, we could trust the hardware
3951 * to always provide zeroes when muted.
3952 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303953 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3954 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955 memset(buffer, 0, bytes);
3956
3957exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003958 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303959 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 pthread_mutex_unlock(&in->lock);
3961
3962 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303963 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303964 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303965 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303966 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303967 in->standby = true;
3968 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303969 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3970 bytes_read = bytes;
3971 memset(buffer, 0, bytes);
3972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003974 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303975 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303976 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303978 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979}
3980
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003981static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982{
3983 return 0;
3984}
3985
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003986static int add_remove_audio_effect(const struct audio_stream *stream,
3987 effect_handle_t effect,
3988 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003990 struct stream_in *in = (struct stream_in *)stream;
3991 int status = 0;
3992 effect_descriptor_t desc;
3993
3994 status = (*effect)->get_descriptor(effect, &desc);
3995 if (status != 0)
3996 return status;
3997
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003998 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003999 pthread_mutex_lock(&in->dev->lock);
4000 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4001 in->enable_aec != enable &&
4002 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4003 in->enable_aec = enable;
4004 if (!in->standby)
4005 select_devices(in->dev, in->usecase);
4006 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004007 if (in->enable_ns != enable &&
4008 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4009 in->enable_ns = enable;
4010 if (!in->standby)
4011 select_devices(in->dev, in->usecase);
4012 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004013 pthread_mutex_unlock(&in->dev->lock);
4014 pthread_mutex_unlock(&in->lock);
4015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 return 0;
4017}
4018
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004019static int in_add_audio_effect(const struct audio_stream *stream,
4020 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004021{
Eric Laurent994a6932013-07-17 11:51:42 -07004022 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004023 return add_remove_audio_effect(stream, effect, true);
4024}
4025
4026static int in_remove_audio_effect(const struct audio_stream *stream,
4027 effect_handle_t effect)
4028{
Eric Laurent994a6932013-07-17 11:51:42 -07004029 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004030 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031}
4032
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304033int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034 audio_io_handle_t handle,
4035 audio_devices_t devices,
4036 audio_output_flags_t flags,
4037 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004038 struct audio_stream_out **stream_out,
4039 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040{
4041 struct audio_device *adev = (struct audio_device *)dev;
4042 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304043 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004044 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004045 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4050
Mingming Yin3a941d42016-02-17 18:08:05 -08004051 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4052 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304053 devices, flags, &out->stream);
4054
4055
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004056 if (!out) {
4057 return -ENOMEM;
4058 }
4059
Haynes Mathew George204045b2015-02-25 20:32:03 -08004060 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004061 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004062 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 if (devices == AUDIO_DEVICE_NONE)
4065 devices = AUDIO_DEVICE_OUT_SPEAKER;
4066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 out->flags = flags;
4068 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004069 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004070 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004071 out->sample_rate = config->sample_rate;
4072 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4073 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004074 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004075 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004076 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304077 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078
Mingming Yin3a941d42016-02-17 18:08:05 -08004079 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4080 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4081 pthread_mutex_lock(&adev->lock);
4082 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4083 ret = read_hdmi_sink_caps(out);
4084 pthread_mutex_unlock(&adev->lock);
4085 if (ret != 0) {
4086 if (ret == -ENOSYS) {
4087 /* ignore and go with default */
4088 ret = 0;
4089 } else {
4090 ALOGE("error reading hdmi sink caps");
4091 goto error_open;
4092 }
4093 }
4094 }
4095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304097 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004098 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004099 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004100 ret = voice_extn_compress_voip_open_output_stream(out);
4101 if (ret != 0) {
4102 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4103 __func__, ret);
4104 goto error_open;
4105 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004106 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304107 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304108 pthread_mutex_lock(&adev->lock);
4109 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4110 pthread_mutex_unlock(&adev->lock);
4111
4112 // reject offload during card offline to allow
4113 // fallback to s/w paths
4114 if (offline) {
4115 ret = -ENODEV;
4116 goto error_open;
4117 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004119 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4120 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4121 ALOGE("%s: Unsupported Offload information", __func__);
4122 ret = -EINVAL;
4123 goto error_open;
4124 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004125
Mingming Yin3a941d42016-02-17 18:08:05 -08004126 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004127 if(config->offload_info.format == 0)
4128 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004129 if (config->offload_info.sample_rate == 0)
4130 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004131 }
4132
Mingming Yin90310102013-11-13 16:57:00 -08004133 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304134 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004135 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136 ret = -EINVAL;
4137 goto error_open;
4138 }
4139
4140 out->compr_config.codec = (struct snd_codec *)
4141 calloc(1, sizeof(struct snd_codec));
4142
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004143 if (!out->compr_config.codec) {
4144 ret = -ENOMEM;
4145 goto error_open;
4146 }
4147
Dhananjay Kumarac341582017-02-23 23:42:25 +05304148 out->stream.pause = out_pause;
4149 out->stream.resume = out_resume;
4150 out->stream.flush = out_flush;
4151 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004152 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004153 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304154 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004155 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304156 } else {
4157 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4158 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004159 }
vivek mehta446c3962015-09-14 10:57:35 -07004160
4161 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004162 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4163 config->format == 0 && config->sample_rate == 0 &&
4164 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004165 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004166 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4167 } else {
4168 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4169 ret = -EEXIST;
4170 goto error_open;
4171 }
vivek mehta446c3962015-09-14 10:57:35 -07004172 }
4173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004174 if (config->offload_info.channel_mask)
4175 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004176 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004177 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004178 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004179 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304180 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004181 ret = -EINVAL;
4182 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004183 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004184
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004185 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004186 out->sample_rate = config->offload_info.sample_rate;
4187
Mingming Yin3ee55c62014-08-04 14:23:35 -07004188 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004189
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304190 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4191 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4192 audio_extn_dolby_send_ddp_endp_params(adev);
4193 audio_extn_dolby_set_dmid(adev);
4194 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004195
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004196 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004197 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004198 out->compr_config.codec->bit_rate =
4199 config->offload_info.bit_rate;
4200 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304201 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004202 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304203 /* Update bit width only for non passthrough usecases.
4204 * For passthrough usecases, the output will always be opened @16 bit
4205 */
4206 if (!audio_extn_passthru_is_passthrough_stream(out))
4207 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304208
4209 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4210 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4211 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4212
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004213 /*TODO: Do we need to change it for passthrough */
4214 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004215
Manish Dewangana6fc5442015-08-24 20:30:31 +05304216 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4217 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304218 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304219 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304220 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4221 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304222
4223 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4224 AUDIO_FORMAT_PCM) {
4225
4226 /*Based on platform support, configure appropriate alsa format for corresponding
4227 *hal input format.
4228 */
4229 out->compr_config.codec->format = hal_format_to_alsa(
4230 config->offload_info.format);
4231
Ashish Jain83a6cc22016-06-28 14:34:17 +05304232 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304233 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304234 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304235
Dhananjay Kumarac341582017-02-23 23:42:25 +05304236 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304237 *hal input format and alsa format might differ based on platform support.
4238 */
4239 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304240 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304241
4242 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4243
4244 /* Check if alsa session is configured with the same format as HAL input format,
4245 * if not then derive correct fragment size needed to accomodate the
4246 * conversion of HAL input format to alsa format.
4247 */
4248 audio_extn_utils_update_direct_pcm_fragment_size(out);
4249
4250 /*if hal input and output fragment size is different this indicates HAL input format is
4251 *not same as the alsa format
4252 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304253 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304254 /*Allocate a buffer to convert input data to the alsa configured format.
4255 *size of convert buffer is equal to the size required to hold one fragment size
4256 *worth of pcm data, this is because flinger does not write more than fragment_size
4257 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304258 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4259 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304260 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4261 ret = -ENOMEM;
4262 goto error_open;
4263 }
4264 }
4265 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4266 out->compr_config.fragment_size =
4267 audio_extn_passthru_get_buffer_size(&config->offload_info);
4268 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4269 } else {
4270 out->compr_config.fragment_size =
4271 platform_get_compress_offload_buffer_size(&config->offload_info);
4272 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4273 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004274
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304275 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4276 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4277 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004278 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304279 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004280
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304281 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4282 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4283 }
4284
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004285 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4286 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004287
Manish Dewangan69426c82017-01-30 17:35:36 +05304288 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4289 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4290 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4291 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4292 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4293 } else {
4294 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4295 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004296
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304297 memset(&out->channel_map_param, 0,
4298 sizeof(struct audio_out_channel_map_param));
4299
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004300 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304301 out->send_next_track_params = false;
4302 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004303 out->offload_state = OFFLOAD_STATE_IDLE;
4304 out->playback_started = 0;
4305
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004306 audio_extn_dts_create_state_notifier_node(out->usecase);
4307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004308 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4309 __func__, config->offload_info.version,
4310 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304311
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304312 /* Check if DSD audio format is supported in codec
4313 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304314 */
4315
4316 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304317 (!platform_check_codec_dsd_support(adev->platform) ||
4318 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304319 ret = -EINVAL;
4320 goto error_open;
4321 }
4322
Ashish Jain5106d362016-05-11 19:23:33 +05304323 /* Disable gapless if any of the following is true
4324 * passthrough playback
4325 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304326 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304327 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304328 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304329 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004330 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304331 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304332 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304333 check_and_set_gapless_mode(adev, false);
4334 } else
4335 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004336
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304337 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004338 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4339 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304340 if (config->format == AUDIO_FORMAT_DSD) {
4341 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4342 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4343 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004344
4345 create_offload_callback_thread(out);
4346
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004347 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304348 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004349 if (ret != 0) {
4350 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4351 __func__, ret);
4352 goto error_open;
4353 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004354 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4355 if (config->sample_rate == 0)
4356 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4357 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4358 config->sample_rate != 8000) {
4359 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4360 ret = -EINVAL;
4361 goto error_open;
4362 }
4363 out->sample_rate = config->sample_rate;
4364 out->config.rate = config->sample_rate;
4365 if (config->format == AUDIO_FORMAT_DEFAULT)
4366 config->format = AUDIO_FORMAT_PCM_16_BIT;
4367 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4368 config->format = AUDIO_FORMAT_PCM_16_BIT;
4369 ret = -EINVAL;
4370 goto error_open;
4371 }
4372 out->format = config->format;
4373 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4374 out->config = pcm_config_afe_proxy_playback;
4375 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004376 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304377 unsigned int channels = 0;
4378 /*Update config params to default if not set by the caller*/
4379 if (config->sample_rate == 0)
4380 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4381 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4382 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4383 if (config->format == AUDIO_FORMAT_DEFAULT)
4384 config->format = AUDIO_FORMAT_PCM_16_BIT;
4385
4386 channels = audio_channel_count_from_out_mask(out->channel_mask);
4387
Ashish Jain83a6cc22016-06-28 14:34:17 +05304388 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4389 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004390 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4391 out->flags);
4392 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304393 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4394 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4395 out->config = pcm_config_low_latency;
4396 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4397 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4398 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304399 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4400 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4401 if (out->config.period_size <= 0) {
4402 ALOGE("Invalid configuration period size is not valid");
4403 ret = -EINVAL;
4404 goto error_open;
4405 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304406 } else {
4407 /* primary path is the default path selected if no other outputs are available/suitable */
4408 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4409 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4410 }
4411 out->hal_ip_format = format = out->format;
4412 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4413 out->hal_op_format = pcm_format_to_hal(out->config.format);
4414 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4415 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004416 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304417 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304418 if (out->hal_ip_format != out->hal_op_format) {
4419 uint32_t buffer_size = out->config.period_size *
4420 format_to_bitwidth_table[out->hal_op_format] *
4421 out->config.channels;
4422 out->convert_buffer = calloc(1, buffer_size);
4423 if (out->convert_buffer == NULL){
4424 ALOGE("Allocation failed for convert buffer for size %d",
4425 out->compr_config.fragment_size);
4426 ret = -ENOMEM;
4427 goto error_open;
4428 }
4429 ALOGD("Convert buffer allocated of size %d", buffer_size);
4430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431 }
4432
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004433 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4434 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304435
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004436 /* TODO remove this hardcoding and check why width is zero*/
4437 if (out->bit_width == 0)
4438 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304439 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004440 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304441 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304442 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304443 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004444 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4445 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4446 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004447 if(adev->primary_output == NULL)
4448 adev->primary_output = out;
4449 else {
4450 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004451 ret = -EEXIST;
4452 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004453 }
4454 }
4455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456 /* Check if this usecase is already existing */
4457 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004458 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4459 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004462 ret = -EEXIST;
4463 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 pthread_mutex_unlock(&adev->lock);
4467
4468 out->stream.common.get_sample_rate = out_get_sample_rate;
4469 out->stream.common.set_sample_rate = out_set_sample_rate;
4470 out->stream.common.get_buffer_size = out_get_buffer_size;
4471 out->stream.common.get_channels = out_get_channels;
4472 out->stream.common.get_format = out_get_format;
4473 out->stream.common.set_format = out_set_format;
4474 out->stream.common.standby = out_standby;
4475 out->stream.common.dump = out_dump;
4476 out->stream.common.set_parameters = out_set_parameters;
4477 out->stream.common.get_parameters = out_get_parameters;
4478 out->stream.common.add_audio_effect = out_add_audio_effect;
4479 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4480 out->stream.get_latency = out_get_latency;
4481 out->stream.set_volume = out_set_volume;
4482 out->stream.write = out_write;
4483 out->stream.get_render_position = out_get_render_position;
4484 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004485 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004486
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004487 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004489 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004490 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491
4492 config->format = out->stream.common.get_format(&out->stream.common);
4493 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4494 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4495
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304496 /*
4497 By locking output stream before registering, we allow the callback
4498 to update stream's state only after stream's initial state is set to
4499 adev state.
4500 */
4501 lock_output_stream(out);
4502 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4503 pthread_mutex_lock(&adev->lock);
4504 out->card_status = adev->card_status;
4505 pthread_mutex_unlock(&adev->lock);
4506 pthread_mutex_unlock(&out->lock);
4507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304509 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004510 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004511
4512 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4513 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4514 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004515 /* setup a channel for client <--> adsp communication for stream events */
4516 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004517 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4518 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004519 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4520 out->usecase, PCM_PLAYBACK);
4521 hdlr_stream_cfg.flags = out->flags;
4522 hdlr_stream_cfg.type = PCM_PLAYBACK;
4523 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4524 &hdlr_stream_cfg);
4525 if (ret) {
4526 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4527 out->adsp_hdlr_stream_handle = NULL;
4528 }
4529 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004530 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4531 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4532 if (ret < 0) {
4533 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4534 out->ip_hdlr_handle = NULL;
4535 }
4536 }
Eric Laurent994a6932013-07-17 11:51:42 -07004537 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004539
4540error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304541 if (out->convert_buffer)
4542 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004543 free(out);
4544 *stream_out = NULL;
4545 ALOGD("%s: exit: ret %d", __func__, ret);
4546 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547}
4548
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304549void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 struct audio_stream_out *stream)
4551{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004552 struct stream_out *out = (struct stream_out *)stream;
4553 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004554 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004555
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304556 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4557
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304558 // must deregister from sndmonitor first to prevent races
4559 // between the callback and close_stream
4560 audio_extn_snd_mon_unregister_listener(out);
4561
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004562 /* close adsp hdrl session before standby */
4563 if (out->adsp_hdlr_stream_handle) {
4564 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4565 if (ret)
4566 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4567 out->adsp_hdlr_stream_handle = NULL;
4568 }
4569
Naresh Tanniru85819452017-05-04 18:55:45 -07004570 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4571 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4572 out->ip_hdlr_handle = NULL;
4573 }
4574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004575 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304576 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004577 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304578 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004579 if(ret != 0)
4580 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4581 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004582 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004583 out_standby(&stream->common);
4584
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004585 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004586 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004587 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004588 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004589 if (out->compr_config.codec != NULL)
4590 free(out->compr_config.codec);
4591 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004592
Ashish Jain83a6cc22016-06-28 14:34:17 +05304593 if (out->convert_buffer != NULL) {
4594 free(out->convert_buffer);
4595 out->convert_buffer = NULL;
4596 }
4597
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004598 if (adev->voice_tx_output == out)
4599 adev->voice_tx_output = NULL;
4600
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304601 if (adev->primary_output == out)
4602 adev->primary_output = NULL;
4603
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004604 pthread_cond_destroy(&out->cond);
4605 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004607 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608}
4609
4610static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4611{
4612 struct audio_device *adev = (struct audio_device *)dev;
4613 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004615 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004616 int ret;
4617 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004619 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304622 if (!parms)
4623 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304624
4625 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004626 status = voice_set_parameters(adev, parms);
4627 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004628 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004630 status = platform_set_parameters(adev->platform, parms);
4631 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004632 goto done;
4633
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004634 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4635 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004636 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4638 adev->bluetooth_nrec = true;
4639 else
4640 adev->bluetooth_nrec = false;
4641 }
4642
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004643 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4644 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4646 adev->screen_off = false;
4647 else
4648 adev->screen_off = true;
4649 }
4650
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004651 ret = str_parms_get_int(parms, "rotation", &val);
4652 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004653 bool reverse_speakers = false;
4654 switch(val) {
4655 // FIXME: note that the code below assumes that the speakers are in the correct placement
4656 // relative to the user when the device is rotated 90deg from its default rotation. This
4657 // assumption is device-specific, not platform-specific like this code.
4658 case 270:
4659 reverse_speakers = true;
4660 break;
4661 case 0:
4662 case 90:
4663 case 180:
4664 break;
4665 default:
4666 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004667 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004668 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004669 if (status == 0) {
4670 if (adev->speaker_lr_swap != reverse_speakers) {
4671 adev->speaker_lr_swap = reverse_speakers;
4672 // only update the selected device if there is active pcm playback
4673 struct audio_usecase *usecase;
4674 struct listnode *node;
4675 list_for_each(node, &adev->usecase_list) {
4676 usecase = node_to_item(node, struct audio_usecase, list);
4677 if (usecase->type == PCM_PLAYBACK) {
4678 select_devices(adev, usecase->id);
4679 break;
4680 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004681 }
4682 }
4683 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004684 }
4685
Mingming Yin514a8bc2014-07-29 15:22:21 -07004686 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4687 if (ret >= 0) {
4688 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4689 adev->bt_wb_speech_enabled = true;
4690 else
4691 adev->bt_wb_speech_enabled = false;
4692 }
4693
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004694 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4695 if (ret >= 0) {
4696 val = atoi(value);
4697 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004698 ALOGV("cache new ext disp type and edid");
4699 ret = platform_get_ext_disp_type(adev->platform);
4700 if (ret < 0) {
4701 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004702 status = ret;
4703 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004704 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004705 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004706 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004707 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004708 /*
4709 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4710 * Per AudioPolicyManager, USB device is higher priority than WFD.
4711 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4712 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4713 * starting voice call on USB
4714 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004715 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4716 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004717 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4718 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004719 }
vivek mehta344576a2016-04-12 18:56:03 -07004720 ALOGV("detected USB connect .. disable proxy");
4721 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004722 }
4723 }
4724
4725 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4726 if (ret >= 0) {
4727 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004728 /*
4729 * The HDMI / Displayport disconnect handling has been moved to
4730 * audio extension to ensure that its parameters are not
4731 * invalidated prior to updating sysfs of the disconnect event
4732 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4733 */
4734 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004735 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004736 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4737 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304738 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4739 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004740 }
vivek mehta344576a2016-04-12 18:56:03 -07004741 ALOGV("detected USB disconnect .. enable proxy");
4742 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004743 }
4744 }
4745
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304746 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4747 if (ret >= 0) {
4748 struct audio_usecase *usecase;
4749 struct listnode *node;
4750 list_for_each(node, &adev->usecase_list) {
4751 usecase = node_to_item(node, struct audio_usecase, list);
4752 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004753 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304754 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08004755
4756 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304757 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08004758 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304759 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304760 //force device switch to re configure encoder
4761 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304762 audio_extn_a2dp_set_handoff_mode(false);
4763 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304764 break;
4765 }
4766 }
4767 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004768
4769 //handle vr audio setparam
4770 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4771 value, sizeof(value));
4772 if (ret >= 0) {
4773 ALOGI("Setting vr mode to be %s", value);
4774 if (!strncmp(value, "true", 4)) {
4775 adev->vr_audio_mode_enabled = true;
4776 ALOGI("Setting vr mode to true");
4777 } else if (!strncmp(value, "false", 5)) {
4778 adev->vr_audio_mode_enabled = false;
4779 ALOGI("Setting vr mode to false");
4780 } else {
4781 ALOGI("wrong vr mode set");
4782 }
4783 }
4784
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304785 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004786done:
4787 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004788 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304789error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004790 ALOGV("%s: exit with code(%d)", __func__, status);
4791 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792}
4793
4794static char* adev_get_parameters(const struct audio_hw_device *dev,
4795 const char *keys)
4796{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004797 struct audio_device *adev = (struct audio_device *)dev;
4798 struct str_parms *reply = str_parms_create();
4799 struct str_parms *query = str_parms_create_str(keys);
4800 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304801 char value[256] = {0};
4802 int ret = 0;
4803
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004804 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004805 if (reply) {
4806 str_parms_destroy(reply);
4807 }
4808 if (query) {
4809 str_parms_destroy(query);
4810 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004811 ALOGE("adev_get_parameters: failed to create query or reply");
4812 return NULL;
4813 }
4814
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004815 //handle vr audio getparam
4816
4817 ret = str_parms_get_str(query,
4818 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4819 value, sizeof(value));
4820
4821 if (ret >= 0) {
4822 bool vr_audio_enabled = false;
4823 pthread_mutex_lock(&adev->lock);
4824 vr_audio_enabled = adev->vr_audio_mode_enabled;
4825 pthread_mutex_unlock(&adev->lock);
4826
4827 ALOGI("getting vr mode to %d", vr_audio_enabled);
4828
4829 if (vr_audio_enabled) {
4830 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4831 "true");
4832 goto exit;
4833 } else {
4834 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4835 "false");
4836 goto exit;
4837 }
4838 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004839
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004840 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004841 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004842 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004843 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304844 pthread_mutex_unlock(&adev->lock);
4845
Naresh Tannirud7205b62014-06-20 02:54:48 +05304846exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004847 str = str_parms_to_str(reply);
4848 str_parms_destroy(query);
4849 str_parms_destroy(reply);
4850
4851 ALOGV("%s: exit: returns - %s", __func__, str);
4852 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853}
4854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004855static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856{
4857 return 0;
4858}
4859
4860static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4861{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004862 int ret;
4863 struct audio_device *adev = (struct audio_device *)dev;
4864 pthread_mutex_lock(&adev->lock);
4865 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004866 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004867 pthread_mutex_unlock(&adev->lock);
4868 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869}
4870
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004871static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4872 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873{
4874 return -ENOSYS;
4875}
4876
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004877static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4878 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879{
4880 return -ENOSYS;
4881}
4882
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004883static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4884 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885{
4886 return -ENOSYS;
4887}
4888
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004889static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4890 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891{
4892 return -ENOSYS;
4893}
4894
4895static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4896{
4897 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899 pthread_mutex_lock(&adev->lock);
4900 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004901 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004903 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004904 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004905 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004906 adev->current_call_output = NULL;
4907 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908 }
4909 pthread_mutex_unlock(&adev->lock);
4910 return 0;
4911}
4912
4913static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4914{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004915 int ret;
4916
4917 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004918 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004919 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4920 pthread_mutex_unlock(&adev->lock);
4921
4922 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004923}
4924
4925static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4926{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004927 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 return 0;
4929}
4930
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004931static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932 const struct audio_config *config)
4933{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004934 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004936 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4937 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938}
4939
4940static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004941 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004942 audio_devices_t devices,
4943 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004944 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304945 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004946 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004947 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948{
4949 struct audio_device *adev = (struct audio_device *)dev;
4950 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004951 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004952 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004953 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304954 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304957 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4958 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304960 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004961
4962 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004963
4964 if (!in) {
4965 ALOGE("failed to allocate input stream");
4966 return -ENOMEM;
4967 }
4968
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304969 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304970 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4971 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004972 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004973 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 in->stream.common.get_sample_rate = in_get_sample_rate;
4976 in->stream.common.set_sample_rate = in_set_sample_rate;
4977 in->stream.common.get_buffer_size = in_get_buffer_size;
4978 in->stream.common.get_channels = in_get_channels;
4979 in->stream.common.get_format = in_get_format;
4980 in->stream.common.set_format = in_set_format;
4981 in->stream.common.standby = in_standby;
4982 in->stream.common.dump = in_dump;
4983 in->stream.common.set_parameters = in_set_parameters;
4984 in->stream.common.get_parameters = in_get_parameters;
4985 in->stream.common.add_audio_effect = in_add_audio_effect;
4986 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4987 in->stream.set_gain = in_set_gain;
4988 in->stream.read = in_read;
4989 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4990
4991 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004992 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994 in->standby = 1;
4995 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004996 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004997 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004998
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304999 in->usecase = USECASE_AUDIO_RECORD;
5000 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5001 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5002 is_low_latency = true;
5003#if LOW_LATENCY_CAPTURE_USE_CASE
5004 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5005#endif
5006 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5007 }
5008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005009 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005010 if (in->realtime) {
5011 in->config = pcm_config_audio_capture_rt;
5012 in->sample_rate = in->config.rate;
5013 in->af_period_multiplier = af_period_multiplier;
5014 } else {
5015 in->config = pcm_config_audio_capture;
5016 in->config.rate = config->sample_rate;
5017 in->sample_rate = config->sample_rate;
5018 in->af_period_multiplier = 1;
5019 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305020 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305022 /* restrict 24 bit capture for unprocessed source only
5023 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5024 */
5025 if (config->format == AUDIO_FORMAT_DEFAULT) {
5026 config->format = AUDIO_FORMAT_PCM_16_BIT;
5027 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5028 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5029 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5030 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5031 bool ret_error = false;
5032 in->bit_width = 24;
5033 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5034 from HAL is 24_packed and 8_24
5035 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5036 24_packed return error indicating supported format is 24_packed
5037 *> In case of any other source requesting 24 bit or float return error
5038 indicating format supported is 16 bit only.
5039
5040 on error flinger will retry with supported format passed
5041 */
5042 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5043 (source != AUDIO_SOURCE_CAMCORDER)) {
5044 config->format = AUDIO_FORMAT_PCM_16_BIT;
5045 if (config->sample_rate > 48000)
5046 config->sample_rate = 48000;
5047 ret_error = true;
5048 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5049 in->config.format = PCM_FORMAT_S24_3LE;
5050 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5051 in->config.format = PCM_FORMAT_S24_LE;
5052 } else {
5053 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5054 ret_error = true;
5055 }
5056
5057 if (ret_error) {
5058 ret = -EINVAL;
5059 goto err_open;
5060 }
5061 }
5062
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305063 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305064 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5065 (adev->mode != AUDIO_MODE_IN_CALL)) {
5066 ret = -EINVAL;
5067 goto err_open;
5068 }
5069
5070 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5071 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005072 if (config->sample_rate == 0)
5073 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5074 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5075 config->sample_rate != 8000) {
5076 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5077 ret = -EINVAL;
5078 goto err_open;
5079 }
5080 if (config->format == AUDIO_FORMAT_DEFAULT)
5081 config->format = AUDIO_FORMAT_PCM_16_BIT;
5082 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5083 config->format = AUDIO_FORMAT_PCM_16_BIT;
5084 ret = -EINVAL;
5085 goto err_open;
5086 }
5087
5088 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5089 in->config = pcm_config_afe_proxy_record;
5090 in->config.channels = channel_count;
5091 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305092 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305093 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5094 in, config, &channel_mask_updated)) {
5095 if (channel_mask_updated == true) {
5096 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5097 __func__, config->channel_mask);
5098 ret = -EINVAL;
5099 goto err_open;
5100 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305101 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005102 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005103 audio_extn_compr_cap_format_supported(config->format) &&
5104 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005105 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305106 } else if (audio_extn_cin_applicable_stream(in)) {
5107 ret = audio_extn_cin_configure_input_stream(in);
5108 if (ret)
5109 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005110 } else {
5111 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005112 if (!in->realtime) {
5113 in->format = config->format;
5114 frame_size = audio_stream_in_frame_size(&in->stream);
5115 buffer_size = get_input_buffer_size(config->sample_rate,
5116 config->format,
5117 channel_count,
5118 is_low_latency);
5119 in->config.period_size = buffer_size / frame_size;
5120 }
5121
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005122 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005123 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005124 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005125 (in->config.rate == 8000 || in->config.rate == 16000 ||
5126 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005127 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5128 voice_extn_compress_voip_open_input_stream(in);
5129 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005130 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305132 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5133 &adev->streams_input_cfg_list,
5134 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305135 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305136
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005137 /* This stream could be for sound trigger lab,
5138 get sound trigger pcm if present */
5139 audio_extn_sound_trigger_check_and_get_session(in);
5140
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305141 lock_input_stream(in);
5142 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5143 pthread_mutex_lock(&adev->lock);
5144 in->card_status = adev->card_status;
5145 pthread_mutex_unlock(&adev->lock);
5146 pthread_mutex_unlock(&in->lock);
5147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005149 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005150 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151
5152err_open:
5153 free(in);
5154 *stream_in = NULL;
5155 return ret;
5156}
5157
5158static void adev_close_input_stream(struct audio_hw_device *dev,
5159 struct audio_stream_in *stream)
5160{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005161 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005162 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005163 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305164
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305165 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005166
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305167 // must deregister from sndmonitor first to prevent races
5168 // between the callback and close_stream
5169 audio_extn_snd_mon_unregister_listener(stream);
5170
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305171 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005172 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305173
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005174 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305175 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005176 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305177 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005178 if (ret != 0)
5179 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5180 __func__, ret);
5181 } else
5182 in_standby(&stream->common);
5183
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005184 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005185 audio_extn_ssr_deinit();
5186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305188 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005189 audio_extn_compr_cap_format_supported(in->config.format))
5190 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305191
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305192 if (audio_extn_cin_attached_usecase(in->usecase))
5193 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005194
Mingming Yinfd7607b2016-01-22 12:48:44 -08005195 if (in->is_st_session) {
5196 ALOGV("%s: sound trigger pcm stop lab", __func__);
5197 audio_extn_sound_trigger_stop_lab(in);
5198 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005199 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200 return;
5201}
5202
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005203static int adev_dump(const audio_hw_device_t *device __unused,
5204 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205{
5206 return 0;
5207}
5208
5209static int adev_close(hw_device_t *device)
5210{
5211 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005212
5213 if (!adev)
5214 return 0;
5215
5216 pthread_mutex_lock(&adev_init_lock);
5217
5218 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305219 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005220 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005221 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305222 audio_extn_utils_release_streams_cfg_lists(
5223 &adev->streams_output_cfg_list,
5224 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305225 if (audio_extn_qaf_is_enabled())
5226 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005227 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005228 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005229 free(adev->snd_dev_ref_cnt);
5230 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005231 if (adev->adm_deinit)
5232 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305233 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005234 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305235 audio_extn_snd_mon_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005236 free(device);
5237 adev = NULL;
5238 }
5239 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 return 0;
5242}
5243
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005244/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5245 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5246 * just that it _might_ work.
5247 */
5248static int period_size_is_plausible_for_low_latency(int period_size)
5249{
5250 switch (period_size) {
5251 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005252 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005253 case 240:
5254 case 320:
5255 case 480:
5256 return 1;
5257 default:
5258 return 0;
5259 }
5260}
5261
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305262static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5263{
5264 bool is_snd_card_status = false;
5265 bool is_ext_device_status = false;
5266 char value[32];
5267 int card = -1;
5268 card_status_t status;
5269
5270 if (cookie != adev || !parms)
5271 return;
5272
5273 if (!parse_snd_card_status(parms, &card, &status)) {
5274 is_snd_card_status = true;
5275 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5276 is_ext_device_status = true;
5277 } else {
5278 // not a valid event
5279 return;
5280 }
5281
5282 pthread_mutex_lock(&adev->lock);
5283 if (card == adev->snd_card || is_ext_device_status) {
5284 if (is_snd_card_status && adev->card_status != status) {
5285 adev->card_status = status;
5286 platform_snd_card_update(adev->platform, status);
5287 audio_extn_fm_set_parameters(adev, parms);
5288 } else if (is_ext_device_status) {
5289 platform_set_parameters(adev->platform, parms);
5290 }
5291 }
5292 pthread_mutex_unlock(&adev->lock);
5293 return;
5294}
5295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296static int adev_open(const hw_module_t *module, const char *name,
5297 hw_device_t **device)
5298{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305299 int ret;
5300
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005301 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5303
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005304 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005305 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005306 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005307 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005308 ALOGD("%s: returning existing instance of adev", __func__);
5309 ALOGD("%s: exit", __func__);
5310 pthread_mutex_unlock(&adev_init_lock);
5311 return 0;
5312 }
5313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005314 adev = calloc(1, sizeof(struct audio_device));
5315
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005316 if (!adev) {
5317 pthread_mutex_unlock(&adev_init_lock);
5318 return -ENOMEM;
5319 }
5320
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005321 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5322
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305323#ifdef DYNAMIC_LOG_ENABLED
5324 register_for_dynamic_logging("hal");
5325#endif
5326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5328 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5329 adev->device.common.module = (struct hw_module_t *)module;
5330 adev->device.common.close = adev_close;
5331
5332 adev->device.init_check = adev_init_check;
5333 adev->device.set_voice_volume = adev_set_voice_volume;
5334 adev->device.set_master_volume = adev_set_master_volume;
5335 adev->device.get_master_volume = adev_get_master_volume;
5336 adev->device.set_master_mute = adev_set_master_mute;
5337 adev->device.get_master_mute = adev_get_master_mute;
5338 adev->device.set_mode = adev_set_mode;
5339 adev->device.set_mic_mute = adev_set_mic_mute;
5340 adev->device.get_mic_mute = adev_get_mic_mute;
5341 adev->device.set_parameters = adev_set_parameters;
5342 adev->device.get_parameters = adev_get_parameters;
5343 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5344 adev->device.open_output_stream = adev_open_output_stream;
5345 adev->device.close_output_stream = adev_close_output_stream;
5346 adev->device.open_input_stream = adev_open_input_stream;
5347 adev->device.close_input_stream = adev_close_input_stream;
5348 adev->device.dump = adev_dump;
5349
5350 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005352 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005353 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005355 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005356 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005357 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005358 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005359 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005360 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005361 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005362 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005363 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305364 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305365 adev->perf_lock_opts[0] = 0x101;
5366 adev->perf_lock_opts[1] = 0x20E;
5367 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005370 adev->platform = platform_init(adev);
5371 if (!adev->platform) {
5372 free(adev->snd_dev_ref_cnt);
5373 free(adev);
5374 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5375 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005376 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305377 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005378 return -EINVAL;
5379 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005380
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305381 if (audio_extn_qaf_is_enabled()) {
5382 ret = audio_extn_qaf_init(adev);
5383 if (ret < 0) {
5384 free(adev);
5385 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5386 *device = NULL;
5387 pthread_mutex_unlock(&adev_init_lock);
5388 pthread_mutex_destroy(&adev->lock);
5389 return ret;
5390 }
5391
5392 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5393 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5394 }
5395
Eric Laurentc4aef752013-09-12 17:45:53 -07005396 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5397 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5398 if (adev->visualizer_lib == NULL) {
5399 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5400 } else {
5401 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5402 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005403 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005404 "visualizer_hal_start_output");
5405 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005406 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005407 "visualizer_hal_stop_output");
5408 }
5409 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305410 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005411 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005412 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005413
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005414 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5415 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5416 if (adev->offload_effects_lib == NULL) {
5417 ALOGE("%s: DLOPEN failed for %s", __func__,
5418 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5419 } else {
5420 ALOGV("%s: DLOPEN successful for %s", __func__,
5421 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5422 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305423 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005424 "offload_effects_bundle_hal_start_output");
5425 adev->offload_effects_stop_output =
5426 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5427 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005428 adev->offload_effects_set_hpx_state =
5429 (int (*)(bool))dlsym(adev->offload_effects_lib,
5430 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305431 adev->offload_effects_get_parameters =
5432 (void (*)(struct str_parms *, struct str_parms *))
5433 dlsym(adev->offload_effects_lib,
5434 "offload_effects_bundle_get_parameters");
5435 adev->offload_effects_set_parameters =
5436 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5437 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005438 }
5439 }
5440
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005441 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5442 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5443 if (adev->adm_lib == NULL) {
5444 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5445 } else {
5446 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5447 adev->adm_init = (adm_init_t)
5448 dlsym(adev->adm_lib, "adm_init");
5449 adev->adm_deinit = (adm_deinit_t)
5450 dlsym(adev->adm_lib, "adm_deinit");
5451 adev->adm_register_input_stream = (adm_register_input_stream_t)
5452 dlsym(adev->adm_lib, "adm_register_input_stream");
5453 adev->adm_register_output_stream = (adm_register_output_stream_t)
5454 dlsym(adev->adm_lib, "adm_register_output_stream");
5455 adev->adm_deregister_stream = (adm_deregister_stream_t)
5456 dlsym(adev->adm_lib, "adm_deregister_stream");
5457 adev->adm_request_focus = (adm_request_focus_t)
5458 dlsym(adev->adm_lib, "adm_request_focus");
5459 adev->adm_abandon_focus = (adm_abandon_focus_t)
5460 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005461 adev->adm_set_config = (adm_set_config_t)
5462 dlsym(adev->adm_lib, "adm_set_config");
5463 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5464 dlsym(adev->adm_lib, "adm_request_focus_v2");
5465 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5466 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5467 adev->adm_on_routing_change = (adm_on_routing_change_t)
5468 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005469 }
5470 }
5471
Mingming Yin514a8bc2014-07-29 15:22:21 -07005472 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005473 //initialize this to false for now,
5474 //this will be set to true through set param
5475 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005476
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005477 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478 *device = &adev->device.common;
5479
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305480 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5481 &adev->streams_output_cfg_list,
5482 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005483
Kiran Kandi910e1862013-10-29 13:29:42 -07005484 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005485
5486 char value[PROPERTY_VALUE_MAX];
5487 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005488 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005489 trial = atoi(value);
5490 if (period_size_is_plausible_for_low_latency(trial)) {
5491 pcm_config_low_latency.period_size = trial;
5492 pcm_config_low_latency.start_threshold = trial / 4;
5493 pcm_config_low_latency.avail_min = trial / 4;
5494 configured_low_latency_capture_period_size = trial;
5495 }
5496 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005497 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005498 trial = atoi(value);
5499 if (period_size_is_plausible_for_low_latency(trial)) {
5500 configured_low_latency_capture_period_size = trial;
5501 }
5502 }
5503
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005504 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005505 af_period_multiplier = atoi(value);
5506 if (af_period_multiplier < 0)
5507 af_period_multiplier = 2;
5508 else if (af_period_multiplier > 4)
5509 af_period_multiplier = 4;
5510
5511 ALOGV("new period_multiplier = %d", af_period_multiplier);
5512 }
5513
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005514 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005515 pthread_mutex_unlock(&adev_init_lock);
5516
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005517 if (adev->adm_init)
5518 adev->adm_data = adev->adm_init();
5519
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305520 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305521 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005522 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305523
5524 audio_extn_snd_mon_init();
5525 pthread_mutex_lock(&adev->lock);
5526 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5527 adev->card_status = CARD_STATUS_ONLINE;
5528 pthread_mutex_unlock(&adev->lock);
5529 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
5530
Eric Laurent994a6932013-07-17 11:51:42 -07005531 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005532 return 0;
5533}
5534
5535static struct hw_module_methods_t hal_module_methods = {
5536 .open = adev_open,
5537};
5538
5539struct audio_module HAL_MODULE_INFO_SYM = {
5540 .common = {
5541 .tag = HARDWARE_MODULE_TAG,
5542 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5543 .hal_api_version = HARDWARE_HAL_API_VERSION,
5544 .id = AUDIO_HARDWARE_MODULE_ID,
5545 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005546 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547 .methods = &hal_module_methods,
5548 },
5549};