blob: df8a9c4948ea47098502eef63df3c3d9e5b6bafb [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
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301488bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1489{
1490 bool ret=false;
1491 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1492 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1493 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1494 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1495 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1496 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1497 ret = true;
1498
1499 return ret;
1500}
1501
1502bool is_a2dp_device(snd_device_t out_snd_device)
1503{
1504 bool ret=false;
1505 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1506 ret = true;
1507
1508 return ret;
1509}
1510
1511bool is_bt_soc_on(struct audio_device *adev)
1512{
1513 struct mixer_ctl *ctl;
1514 char *mixer_ctl_name = "BT SOC status";
1515 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1516 bool bt_soc_status = true;
1517 if (!ctl) {
1518 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1519 __func__, mixer_ctl_name);
1520 /*This is to ensure we dont break targets which dont have the kernel change*/
1521 return true;
1522 }
1523 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1524 ALOGD("BT SOC status: %d",bt_soc_status);
1525 return bt_soc_status;
1526}
1527
1528int out_standby_l(struct audio_stream *stream);
1529
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001530int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001532 snd_device_t out_snd_device = SND_DEVICE_NONE;
1533 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 struct audio_usecase *usecase = NULL;
1535 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001536 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001537 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001538 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001539 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301541 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1542
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 usecase = get_usecase_from_list(adev, uc_id);
1544 if (usecase == NULL) {
1545 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1546 return -EINVAL;
1547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001549 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001550 (usecase->type == VOIP_CALL) ||
1551 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301552 if(usecase->stream.out == NULL) {
1553 ALOGE("%s: stream.out is NULL", __func__);
1554 return -EINVAL;
1555 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001556 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001557 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001558 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 usecase->devices = usecase->stream.out->devices;
1560 } else {
1561 /*
1562 * If the voice call is active, use the sound devices of voice call usecase
1563 * so that it would not result any device switch. All the usecases will
1564 * be switched to new device when select_devices() is called for voice call
1565 * usecase. This is to avoid switching devices for voice call when
1566 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001567 * choose voice call device only if the use case device is
1568 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001569 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001570 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001571 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001572 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001573 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1574 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301575 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1576 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001577 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 in_snd_device = vc_usecase->in_snd_device;
1579 out_snd_device = vc_usecase->out_snd_device;
1580 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001581 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001582 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001583 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001584 if ((voip_usecase != NULL) &&
1585 (usecase->type == PCM_PLAYBACK) &&
1586 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001587 out_snd_device_backend_match = platform_check_backends_match(
1588 voip_usecase->out_snd_device,
1589 platform_get_output_snd_device(
1590 adev->platform,
1591 usecase->stream.out));
1592 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001593 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001594 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1595 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001596 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001597 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001598 in_snd_device = voip_usecase->in_snd_device;
1599 out_snd_device = voip_usecase->out_snd_device;
1600 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001601 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001602 hfp_ucid = audio_extn_hfp_get_usecase();
1603 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001604 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001605 in_snd_device = hfp_usecase->in_snd_device;
1606 out_snd_device = hfp_usecase->out_snd_device;
1607 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 }
1609 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301610 if (usecase->stream.out == NULL) {
1611 ALOGE("%s: stream.out is NULL", __func__);
1612 return -EINVAL;
1613 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001614 usecase->devices = usecase->stream.out->devices;
1615 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001616 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001617 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001618 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001619 if (usecase->stream.out == adev->primary_output &&
1620 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001621 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001622 select_devices(adev, adev->active_input->usecase);
1623 }
1624 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301626 if (usecase->stream.in == NULL) {
1627 ALOGE("%s: stream.in is NULL", __func__);
1628 return -EINVAL;
1629 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630 usecase->devices = usecase->stream.in->device;
1631 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001632 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001633 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001634 if (adev->active_input &&
1635 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301636 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1637 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1638 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001639 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001640 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001641 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1642 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001643 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001644 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001645 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 }
1647 }
1648
1649 if (out_snd_device == usecase->out_snd_device &&
1650 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301651
1652 if (!force_device_switch(usecase))
1653 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654 }
1655
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301656 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1657 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1658 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1659 return 0;
1660 }
1661
sangwoobc677242013-08-08 16:53:43 +09001662 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001663 out_snd_device, platform_get_snd_device_name(out_snd_device),
1664 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 /*
1667 * Limitation: While in call, to do a device switch we need to disable
1668 * and enable both RX and TX devices though one of them is same as current
1669 * device.
1670 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001671 if ((usecase->type == VOICE_CALL) &&
1672 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1673 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001674 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001675 }
1676
1677 if (((usecase->type == VOICE_CALL) ||
1678 (usecase->type == VOIP_CALL)) &&
1679 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1680 /* Disable sidetone only if voice/voip call already exists */
1681 if (voice_is_call_state_active(adev) ||
1682 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001683 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001684
1685 /* Disable aanc only if voice call exists */
1686 if (voice_is_call_state_active(adev))
1687 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001688 }
1689
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001690 /* Disable current sound devices */
1691 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001692 disable_audio_route(adev, usecase);
1693 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001697 disable_audio_route(adev, usecase);
1698 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 }
1700
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001701 /* Applicable only on the targets that has external modem.
1702 * New device information should be sent to modem before enabling
1703 * the devices to reduce in-call device switch time.
1704 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001705 if ((usecase->type == VOICE_CALL) &&
1706 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1707 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001708 status = platform_switch_voice_call_enable_device_config(adev->platform,
1709 out_snd_device,
1710 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001711 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 /* Enable new sound devices */
1714 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001715 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301716 if (platform_check_codec_asrc_support(adev->platform))
1717 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001718 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719 }
1720
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001721 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301722 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001723 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001724 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725
Avinash Vaish71a8b972014-07-24 15:36:33 +05301726 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001727 status = platform_switch_voice_call_device_post(adev->platform,
1728 out_snd_device,
1729 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301730 enable_audio_route_for_voice_usecases(adev, usecase);
1731 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001732
sangwoo170731f2013-06-08 15:36:36 +09001733 usecase->in_snd_device = in_snd_device;
1734 usecase->out_snd_device = out_snd_device;
1735
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301736 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1737 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301738 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001739 if ((24 == usecase->stream.out->bit_width) &&
1740 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1741 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1742 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1743 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1744 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1745 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1746 /*
1747 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1748 * configured device sample rate, if not update the COPP rate to be equal to the
1749 * device sample rate, else open COPP at stream sample rate
1750 */
1751 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1752 usecase->stream.out->sample_rate,
1753 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301754 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1755 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001756 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1757 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1758 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1759 }
1760
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001761 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001762 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001763 audio_extn_gef_notify_device_config(
1764 usecase->stream.out->devices,
1765 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001766 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001767 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001768 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301769 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001770 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001771
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001772 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001773 /* Enable aanc only if voice call exists */
1774 if (voice_is_call_state_active(adev))
1775 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1776
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001777 /* Enable sidetone only if other voice/voip call already exists */
1778 if (voice_is_call_state_active(adev) ||
1779 voice_extn_compress_voip_is_started(adev))
1780 voice_set_sidetone(adev, out_snd_device, true);
1781 }
1782
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001783 /* Applicable only on the targets that has external modem.
1784 * Enable device command should be sent to modem only after
1785 * enabling voice call mixer controls
1786 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001787 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001788 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1789 out_snd_device,
1790 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301791
1792 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1793
1794 if (usecase->type == VOIP_CALL) {
1795 if (adev->active_input != NULL &&
1796 !adev->active_input->standby) {
1797 if (is_bt_soc_on(adev) == false){
1798 ALOGD("BT SCO MIC disconnected while in connection");
1799 if (adev->active_input->pcm != NULL)
1800 pcm_stop(adev->active_input->pcm);
1801 }
1802 }
1803 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1804 && usecase->stream.out->started) {
1805 if (is_bt_soc_on(adev) == false) {
1806 ALOGD("BT SCO/A2DP disconnected while in connection");
1807 out_standby_l(&usecase->stream.out->stream.common);
1808 }
1809 }
1810 } else if ((usecase->stream.out != NULL) &&
1811 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1812 usecase->stream.out->started) {
1813 if (is_bt_soc_on(adev) == false) {
1814 ALOGD("BT SCO/A2dp disconnected while in connection");
1815 out_standby_l(&usecase->stream.out->stream.common);
1816 }
1817 }
1818 }
1819
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301820 ALOGD("%s: done",__func__);
1821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822 return status;
1823}
1824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825static int stop_input_stream(struct stream_in *in)
1826{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301827 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828 struct audio_usecase *uc_info;
1829 struct audio_device *adev = in->dev;
1830
Eric Laurent994a6932013-07-17 11:51:42 -07001831 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 uc_info = get_usecase_from_list(adev, in->usecase);
1834 if (uc_info == NULL) {
1835 ALOGE("%s: Could not find the usecase (%d) in the list",
1836 __func__, in->usecase);
1837 return -EINVAL;
1838 }
1839
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001840 /* Close in-call recording streams */
1841 voice_check_and_stop_incall_rec_usecase(adev, in);
1842
Eric Laurent150dbfe2013-02-27 14:31:02 -08001843 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001844 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001845
1846 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001847 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001849 list_remove(&uc_info->list);
1850 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001852 adev->active_input = get_next_active_input(adev);
1853
Eric Laurent994a6932013-07-17 11:51:42 -07001854 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 return ret;
1856}
1857
1858int start_input_stream(struct stream_in *in)
1859{
1860 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001861 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 struct audio_usecase *uc_info;
1863 struct audio_device *adev = in->dev;
1864
Mingming Yin2664a5b2015-09-03 10:53:11 -07001865 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1866 if (get_usecase_from_list(adev, usecase) == NULL)
1867 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301868 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1869 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001870
Naresh Tanniru80659832014-06-04 18:17:56 +05301871
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301872 if (CARD_STATUS_OFFLINE == in->card_status||
1873 CARD_STATUS_OFFLINE == adev->card_status) {
1874 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301875 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301876 goto error_config;
1877 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301878
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301879 if (audio_is_bluetooth_sco_device(in->device)) {
1880 if (!adev->bt_sco_on) {
1881 ALOGE("%s: SCO profile is not ready, return error", __func__);
1882 ret = -EIO;
1883 goto error_config;
1884 }
1885 }
1886
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001887 /* Check if source matches incall recording usecase criteria */
1888 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1889 if (ret)
1890 goto error_config;
1891 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001892 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1893
1894 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1895 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1896 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001897 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001898 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001899
Eric Laurentb23d5282013-05-14 15:27:20 -07001900 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901 if (in->pcm_device_id < 0) {
1902 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1903 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001904 ret = -EINVAL;
1905 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907
1908 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001910
1911 if (!uc_info) {
1912 ret = -ENOMEM;
1913 goto error_config;
1914 }
1915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 uc_info->id = in->usecase;
1917 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001918 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 uc_info->devices = in->device;
1920 uc_info->in_snd_device = SND_DEVICE_NONE;
1921 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001923 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301924 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1925 adev->perf_lock_opts,
1926 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301929 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1930 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001931
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301932 if (audio_extn_cin_attached_usecase(in->usecase)) {
1933 ret = audio_extn_cin_start_input_stream(in);
1934 if (ret)
1935 goto error_open;
1936 else
1937 goto done_open;
1938 }
1939
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001940 unsigned int flags = PCM_IN;
1941 unsigned int pcm_open_retry_count = 0;
1942
1943 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1944 flags |= PCM_MMAP | PCM_NOIRQ;
1945 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001946 } else if (in->realtime) {
1947 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001948 }
1949
1950 while (1) {
1951 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1952 flags, &in->config);
1953 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1954 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1955 if (in->pcm != NULL) {
1956 pcm_close(in->pcm);
1957 in->pcm = NULL;
1958 }
1959 if (pcm_open_retry_count-- == 0) {
1960 ret = -EIO;
1961 goto error_open;
1962 }
1963 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1964 continue;
1965 }
1966 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001968
1969 ALOGV("%s: pcm_prepare", __func__);
1970 ret = pcm_prepare(in->pcm);
1971 if (ret < 0) {
1972 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1973 pcm_close(in->pcm);
1974 in->pcm = NULL;
1975 goto error_open;
1976 }
1977
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001978 register_in_stream(in);
1979 if (in->realtime) {
1980 ret = pcm_start(in->pcm);
1981 if (ret < 0)
1982 goto error_open;
1983 }
1984
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301985done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301986 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001987 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001988
Eric Laurentc8400632013-02-14 19:04:54 -08001989 return ret;
1990
1991error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301992 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001994error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301995 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301996 /*
1997 * sleep 50ms to allow sufficient time for kernel
1998 * drivers to recover incases like SSR.
1999 */
2000 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002001 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002002
2003 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004}
2005
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002006void lock_input_stream(struct stream_in *in)
2007{
2008 pthread_mutex_lock(&in->pre_lock);
2009 pthread_mutex_lock(&in->lock);
2010 pthread_mutex_unlock(&in->pre_lock);
2011}
2012
2013void lock_output_stream(struct stream_out *out)
2014{
2015 pthread_mutex_lock(&out->pre_lock);
2016 pthread_mutex_lock(&out->lock);
2017 pthread_mutex_unlock(&out->pre_lock);
2018}
2019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020/* must be called with out->lock locked */
2021static int send_offload_cmd_l(struct stream_out* out, int command)
2022{
2023 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2024
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002025 if (!cmd) {
2026 ALOGE("failed to allocate mem for command 0x%x", command);
2027 return -ENOMEM;
2028 }
2029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 ALOGVV("%s %d", __func__, command);
2031
2032 cmd->cmd = command;
2033 list_add_tail(&out->offload_cmd_list, &cmd->node);
2034 pthread_cond_signal(&out->offload_cond);
2035 return 0;
2036}
2037
2038/* must be called iwth out->lock locked */
2039static void stop_compressed_output_l(struct stream_out *out)
2040{
2041 out->offload_state = OFFLOAD_STATE_IDLE;
2042 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002043 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 if (out->compr != NULL) {
2045 compress_stop(out->compr);
2046 while (out->offload_thread_blocked) {
2047 pthread_cond_wait(&out->cond, &out->lock);
2048 }
2049 }
2050}
2051
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002052bool is_offload_usecase(audio_usecase_t uc_id)
2053{
2054 unsigned int i;
2055 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2056 if (uc_id == offload_usecases[i])
2057 return true;
2058 }
2059 return false;
2060}
2061
Dhananjay Kumarac341582017-02-23 23:42:25 +05302062static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002063{
vivek mehta446c3962015-09-14 10:57:35 -07002064 audio_usecase_t ret_uc = USECASE_INVALID;
2065 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002066 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002067 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302068 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002069 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2070 else
2071 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002072
vivek mehta446c3962015-09-14 10:57:35 -07002073 pthread_mutex_lock(&adev->lock);
2074 if (get_usecase_from_list(adev, ret_uc) != NULL)
2075 ret_uc = USECASE_INVALID;
2076 pthread_mutex_unlock(&adev->lock);
2077
2078 return ret_uc;
2079 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002080
2081 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002082 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2083 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2084 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2085 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002086 break;
2087 }
2088 }
vivek mehta446c3962015-09-14 10:57:35 -07002089
2090 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2091 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002092}
2093
2094static void free_offload_usecase(struct audio_device *adev,
2095 audio_usecase_t uc_id)
2096{
vivek mehta446c3962015-09-14 10:57:35 -07002097 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002098 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002099
2100 if (!adev->multi_offload_enable)
2101 return;
2102
2103 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2104 if (offload_usecases[offload_uc_index] == uc_id) {
2105 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002106 break;
2107 }
2108 }
2109 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2110}
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112static void *offload_thread_loop(void *context)
2113{
2114 struct stream_out *out = (struct stream_out *) context;
2115 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002116 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2119 set_sched_policy(0, SP_FOREGROUND);
2120 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2121
2122 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002123 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 for (;;) {
2125 struct offload_cmd *cmd = NULL;
2126 stream_callback_event_t event;
2127 bool send_callback = false;
2128
2129 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2130 __func__, list_empty(&out->offload_cmd_list),
2131 out->offload_state);
2132 if (list_empty(&out->offload_cmd_list)) {
2133 ALOGV("%s SLEEPING", __func__);
2134 pthread_cond_wait(&out->offload_cond, &out->lock);
2135 ALOGV("%s RUNNING", __func__);
2136 continue;
2137 }
2138
2139 item = list_head(&out->offload_cmd_list);
2140 cmd = node_to_item(item, struct offload_cmd, node);
2141 list_remove(item);
2142
2143 ALOGVV("%s STATE %d CMD %d out->compr %p",
2144 __func__, out->offload_state, cmd->cmd, out->compr);
2145
2146 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2147 free(cmd);
2148 break;
2149 }
2150
2151 if (out->compr == NULL) {
2152 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002153 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 pthread_cond_signal(&out->cond);
2155 continue;
2156 }
2157 out->offload_thread_blocked = true;
2158 pthread_mutex_unlock(&out->lock);
2159 send_callback = false;
2160 switch(cmd->cmd) {
2161 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002162 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002164 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 send_callback = true;
2166 event = STREAM_CBK_EVENT_WRITE_READY;
2167 break;
2168 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002169 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302170 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002171 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302172 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002173 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302174 if (ret < 0)
2175 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302176 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302177 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002178 compress_drain(out->compr);
2179 else
2180 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302181 if (ret != -ENETRESET) {
2182 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302183 pthread_mutex_lock(&out->lock);
2184 out->send_new_metadata = 1;
2185 out->send_next_track_params = true;
2186 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302187 event = STREAM_CBK_EVENT_DRAIN_READY;
2188 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2189 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302190 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 break;
2192 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002193 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002195 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 send_callback = true;
2197 event = STREAM_CBK_EVENT_DRAIN_READY;
2198 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302199 case OFFLOAD_CMD_ERROR:
2200 ALOGD("copl(%p): sending error callback to AF", out);
2201 send_callback = true;
2202 event = STREAM_CBK_EVENT_ERROR;
2203 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 default:
2205 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2206 break;
2207 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002208 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 out->offload_thread_blocked = false;
2210 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002211 if (send_callback && out->client_callback) {
2212 ALOGVV("%s: sending client_callback event %d", __func__, event);
2213 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002214 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 free(cmd);
2216 }
2217
2218 pthread_cond_signal(&out->cond);
2219 while (!list_empty(&out->offload_cmd_list)) {
2220 item = list_head(&out->offload_cmd_list);
2221 list_remove(item);
2222 free(node_to_item(item, struct offload_cmd, node));
2223 }
2224 pthread_mutex_unlock(&out->lock);
2225
2226 return NULL;
2227}
2228
2229static int create_offload_callback_thread(struct stream_out *out)
2230{
2231 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2232 list_init(&out->offload_cmd_list);
2233 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2234 offload_thread_loop, out);
2235 return 0;
2236}
2237
2238static int destroy_offload_callback_thread(struct stream_out *out)
2239{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002240 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 stop_compressed_output_l(out);
2242 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2243
2244 pthread_mutex_unlock(&out->lock);
2245 pthread_join(out->offload_thread, (void **) NULL);
2246 pthread_cond_destroy(&out->offload_cond);
2247
2248 return 0;
2249}
2250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251static int stop_output_stream(struct stream_out *out)
2252{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302253 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 struct audio_usecase *uc_info;
2255 struct audio_device *adev = out->dev;
2256
Eric Laurent994a6932013-07-17 11:51:42 -07002257 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 uc_info = get_usecase_from_list(adev, out->usecase);
2260 if (uc_info == NULL) {
2261 ALOGE("%s: Could not find the usecase (%d) in the list",
2262 __func__, out->usecase);
2263 return -EINVAL;
2264 }
2265
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002266 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302267 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002268 if (adev->visualizer_stop_output != NULL)
2269 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002270
2271 audio_extn_dts_remove_state_notifier_node(out->usecase);
2272
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002273 if (adev->offload_effects_stop_output != NULL)
2274 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2275 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002276
Eric Laurent150dbfe2013-02-27 14:31:02 -08002277 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002278 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279
2280 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002281 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002283 list_remove(&uc_info->list);
2284 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302285 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002286 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302287 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002288 ALOGV("Disable passthrough , reset mixer to pcm");
2289 /* NO_PASSTHROUGH */
2290 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002291 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002292 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2293 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002294
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302295 /* Must be called after removing the usecase from list */
2296 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302297 audio_extn_keep_alive_start();
2298
Naresh Tanniru85819452017-05-04 18:55:45 -07002299 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2300 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2301 if (ret < 0)
2302 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2303 }
2304
Eric Laurent994a6932013-07-17 11:51:42 -07002305 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 return ret;
2307}
2308
2309int start_output_stream(struct stream_out *out)
2310{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 struct audio_usecase *uc_info;
2313 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002314 char mixer_ctl_name[128];
2315 struct mixer_ctl *ctl = NULL;
2316 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002318 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2319 ret = -EINVAL;
2320 goto error_config;
2321 }
2322
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302323 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2324 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2325 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302326
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302327 if (CARD_STATUS_OFFLINE == out->card_status ||
2328 CARD_STATUS_OFFLINE == adev->card_status) {
2329 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302330 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302331 goto error_config;
2332 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302333
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302334 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2335 if (!audio_extn_a2dp_is_ready()) {
2336 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2337 //combo usecase just by pass a2dp
2338 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2339 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2340 } else {
2341 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2342 ret = -EAGAIN;
2343 goto error_config;
2344 }
2345 }
2346 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302347 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2348 if (!adev->bt_sco_on) {
2349 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2350 //combo usecase just by pass a2dp
2351 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2352 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2353 } else {
2354 ALOGE("%s: SCO profile is not ready, return error", __func__);
2355 ret = -EAGAIN;
2356 goto error_config;
2357 }
2358 }
2359 }
2360
Eric Laurentb23d5282013-05-14 15:27:20 -07002361 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 if (out->pcm_device_id < 0) {
2363 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2364 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002365 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002366 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
2368
2369 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002370
2371 if (!uc_info) {
2372 ret = -ENOMEM;
2373 goto error_config;
2374 }
2375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 uc_info->id = out->usecase;
2377 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002378 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002379 uc_info->devices = out->devices;
2380 uc_info->in_snd_device = SND_DEVICE_NONE;
2381 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002382 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302384 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2385 adev->perf_lock_opts,
2386 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302387
2388 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2389 audio_extn_keep_alive_stop();
2390 if (audio_extn_passthru_is_enabled() &&
2391 audio_extn_passthru_is_passthrough_stream(out)) {
2392 audio_extn_passthru_on_start(out);
2393 audio_extn_passthru_update_stream_configuration(adev, out);
2394 }
2395 }
2396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002397 select_devices(adev, out->usecase);
2398
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002399 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2400 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002401 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002402 unsigned int flags = PCM_OUT;
2403 unsigned int pcm_open_retry_count = 0;
2404 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2405 flags |= PCM_MMAP | PCM_NOIRQ;
2406 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002407 } else if (out->realtime) {
2408 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002409 } else
2410 flags |= PCM_MONOTONIC;
2411
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002412 if ((adev->vr_audio_mode_enabled) &&
2413 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2414 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2415 "PCM_Dev %d Topology", out->pcm_device_id);
2416 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2417 if (!ctl) {
2418 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2419 __func__, mixer_ctl_name);
2420 } else {
2421 //if success use ULLPP
2422 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2423 __func__, mixer_ctl_name, out->pcm_device_id);
2424 //There is a still a possibility that some sessions
2425 // that request for FAST|RAW when 3D audio is active
2426 //can go through ULLPP. Ideally we expects apps to
2427 //listen to audio focus and stop concurrent playback
2428 //Also, we will look for mode flag (voice_in_communication)
2429 //before enabling the realtime flag.
2430 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2431 }
2432 }
2433
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002434 while (1) {
2435 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2436 flags, &out->config);
2437 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2438 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2439 if (out->pcm != NULL) {
2440 pcm_close(out->pcm);
2441 out->pcm = NULL;
2442 }
2443 if (pcm_open_retry_count-- == 0) {
2444 ret = -EIO;
2445 goto error_open;
2446 }
2447 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2448 continue;
2449 }
2450 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002452
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002453 ALOGV("%s: pcm_prepare", __func__);
2454 if (pcm_is_ready(out->pcm)) {
2455 ret = pcm_prepare(out->pcm);
2456 if (ret < 0) {
2457 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2458 pcm_close(out->pcm);
2459 out->pcm = NULL;
2460 goto error_open;
2461 }
2462 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302463 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302464 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2465
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002467 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302468 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002470 out->compr = compress_open(adev->snd_card,
2471 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002472 COMPRESS_IN, &out->compr_config);
2473 if (out->compr && !is_compress_ready(out->compr)) {
2474 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2475 compress_close(out->compr);
2476 out->compr = NULL;
2477 ret = -EIO;
2478 goto error_open;
2479 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302480 /* compress_open sends params of the track, so reset the flag here */
2481 out->is_compr_metadata_avail = false;
2482
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002483 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002485
Fred Oh3f43e742015-03-04 18:42:34 -08002486 /* Since small bufs uses blocking writes, a write will be blocked
2487 for the default max poll time (20s) in the event of an SSR.
2488 Reduce the poll time to observe and deal with SSR faster.
2489 */
Ashish Jain5106d362016-05-11 19:23:33 +05302490 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002491 compress_set_max_poll_wait(out->compr, 1000);
2492 }
2493
Manish Dewangan69426c82017-01-30 17:35:36 +05302494 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302495 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302496
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002497 audio_extn_dts_create_state_notifier_node(out->usecase);
2498 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2499 popcount(out->channel_mask),
2500 out->playback_started);
2501
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002502#ifdef DS1_DOLBY_DDP_ENABLED
2503 if (audio_extn_is_dolby_format(out->format))
2504 audio_extn_dolby_send_ddp_endp_params(adev);
2505#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302506 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2507 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002508 if (adev->visualizer_start_output != NULL)
2509 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2510 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302511 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002512 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002515
2516 if (ret == 0) {
2517 register_out_stream(out);
2518 if (out->realtime) {
2519 ret = pcm_start(out->pcm);
2520 if (ret < 0)
2521 goto error_open;
2522 }
2523 }
2524
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302525 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002526 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002527
Naresh Tanniru85819452017-05-04 18:55:45 -07002528 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2529 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out);
2530 if (ret < 0)
2531 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2532 }
2533
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002534 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302536 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002538error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302539 /*
2540 * sleep 50ms to allow sufficient time for kernel
2541 * drivers to recover incases like SSR.
2542 */
2543 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002544 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545}
2546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547static int check_input_parameters(uint32_t sample_rate,
2548 audio_format_t format,
2549 int channel_count)
2550{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002551 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302553 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2554 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2555 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002556 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302557 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002558
2559 switch (channel_count) {
2560 case 1:
2561 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302562 case 3:
2563 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002564 case 6:
2565 break;
2566 default:
2567 ret = -EINVAL;
2568 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569
2570 switch (sample_rate) {
2571 case 8000:
2572 case 11025:
2573 case 12000:
2574 case 16000:
2575 case 22050:
2576 case 24000:
2577 case 32000:
2578 case 44100:
2579 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302580 case 96000:
2581 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 break;
2583 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002584 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 }
2586
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002587 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588}
2589
2590static size_t get_input_buffer_size(uint32_t sample_rate,
2591 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002592 int channel_count,
2593 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594{
2595 size_t size = 0;
2596
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002597 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2598 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002600 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002601 if (is_low_latency)
2602 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302603
2604 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002606 /* make sure the size is multiple of 32 bytes
2607 * At 48 kHz mono 16-bit PCM:
2608 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2609 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2610 */
2611 size += 0x1f;
2612 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002613
2614 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615}
2616
Ashish Jain058165c2016-09-28 23:18:48 +05302617static size_t get_output_period_size(uint32_t sample_rate,
2618 audio_format_t format,
2619 int channel_count,
2620 int duration /*in millisecs*/)
2621{
2622 size_t size = 0;
2623 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2624
2625 if ((duration == 0) || (sample_rate == 0) ||
2626 (bytes_per_sample == 0) || (channel_count == 0)) {
2627 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2628 bytes_per_sample, channel_count);
2629 return -EINVAL;
2630 }
2631
2632 size = (sample_rate *
2633 duration *
2634 bytes_per_sample *
2635 channel_count) / 1000;
2636 /*
2637 * To have same PCM samples for all channels, the buffer size requires to
2638 * be multiple of (number of channels * bytes per sample)
2639 * For writes to succeed, the buffer must be written at address which is multiple of 32
2640 */
2641 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2642
2643 return (size/(channel_count * bytes_per_sample));
2644}
2645
Ashish Jain5106d362016-05-11 19:23:33 +05302646static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2647{
2648 uint64_t actual_frames_rendered = 0;
2649 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2650
2651 /* This adjustment accounts for buffering after app processor.
2652 * It is based on estimated DSP latency per use case, rather than exact.
2653 */
2654 int64_t platform_latency = platform_render_latency(out->usecase) *
2655 out->sample_rate / 1000000LL;
2656
2657 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2658 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2659 * hence only estimate.
2660 */
2661 int64_t signed_frames = out->written - kernel_buffer_size;
2662
2663 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2664
2665 if (signed_frames > 0)
2666 actual_frames_rendered = signed_frames;
2667
2668 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2669 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2670 (long long int)out->written, (int)kernel_buffer_size,
2671 audio_bytes_per_sample(out->compr_config.codec->format),
2672 popcount(out->channel_mask));
2673
2674 return actual_frames_rendered;
2675}
2676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002681 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682}
2683
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002684static int out_set_sample_rate(struct audio_stream *stream __unused,
2685 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686{
2687 return -ENOSYS;
2688}
2689
2690static size_t out_get_buffer_size(const struct audio_stream *stream)
2691{
2692 struct stream_out *out = (struct stream_out *)stream;
2693
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302694 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2695 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2696 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2697 else
2698 return out->compr_config.fragment_size;
2699 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002700 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302701 else if (is_offload_usecase(out->usecase) &&
2702 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302703 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002705 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002706 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707}
2708
2709static uint32_t out_get_channels(const struct audio_stream *stream)
2710{
2711 struct stream_out *out = (struct stream_out *)stream;
2712
2713 return out->channel_mask;
2714}
2715
2716static audio_format_t out_get_format(const struct audio_stream *stream)
2717{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002718 struct stream_out *out = (struct stream_out *)stream;
2719
2720 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721}
2722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002723static int out_set_format(struct audio_stream *stream __unused,
2724 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
2726 return -ENOSYS;
2727}
2728
2729static int out_standby(struct audio_stream *stream)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302734 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2735 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002737 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002739 if (adev->adm_deregister_stream)
2740 adev->adm_deregister_stream(adev->adm_data, out->handle);
2741
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002742 if (is_offload_usecase(out->usecase))
2743 stop_compressed_output_l(out);
2744
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002745 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002747 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2748 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302749 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002750 pthread_mutex_unlock(&adev->lock);
2751 pthread_mutex_unlock(&out->lock);
2752 ALOGD("VOIP output entered standby");
2753 return 0;
2754 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002755 if (out->pcm) {
2756 pcm_close(out->pcm);
2757 out->pcm = NULL;
2758 }
2759 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002760 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302761 out->send_next_track_params = false;
2762 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002763 out->gapless_mdata.encoder_delay = 0;
2764 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 if (out->compr != NULL) {
2766 compress_close(out->compr);
2767 out->compr = NULL;
2768 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002769 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002771 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 }
2773 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302774 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 return 0;
2776}
2777
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302778static int out_on_error(struct audio_stream *stream)
2779{
2780 struct stream_out *out = (struct stream_out *)stream;
2781 bool do_standby = false;
2782
2783 lock_output_stream(out);
2784 if (!out->standby) {
2785 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2786 stop_compressed_output_l(out);
2787 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2788 } else
2789 do_standby = true;
2790 }
2791 pthread_mutex_unlock(&out->lock);
2792
2793 if (do_standby)
2794 return out_standby(&out->stream.common);
2795
2796 return 0;
2797}
2798
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302799/*
2800 *standby implementation without locks, assumes that the callee already
2801 *has taken adev and out lock.
2802 */
2803int out_standby_l(struct audio_stream *stream)
2804{
2805 struct stream_out *out = (struct stream_out *)stream;
2806 struct audio_device *adev = out->dev;
2807
2808 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2809 stream, out->usecase, use_case_table[out->usecase]);
2810
2811 if (!out->standby) {
2812 if (adev->adm_deregister_stream)
2813 adev->adm_deregister_stream(adev->adm_data, out->handle);
2814
2815 if (is_offload_usecase(out->usecase))
2816 stop_compressed_output_l(out);
2817
2818 out->standby = true;
2819 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2820 voice_extn_compress_voip_close_output_stream(stream);
2821 out->started = 0;
2822 ALOGD("VOIP output entered standby");
2823 return 0;
2824 } else if (!is_offload_usecase(out->usecase)) {
2825 if (out->pcm) {
2826 pcm_close(out->pcm);
2827 out->pcm = NULL;
2828 }
2829 } else {
2830 ALOGD("copl(%p):standby", out);
2831 out->send_next_track_params = false;
2832 out->is_compr_metadata_avail = false;
2833 out->gapless_mdata.encoder_delay = 0;
2834 out->gapless_mdata.encoder_padding = 0;
2835 if (out->compr != NULL) {
2836 compress_close(out->compr);
2837 out->compr = NULL;
2838 }
2839 }
2840 stop_output_stream(out);
2841 }
2842 ALOGD("%s: exit", __func__);
2843 return 0;
2844}
2845
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002846static int out_dump(const struct audio_stream *stream __unused,
2847 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848{
2849 return 0;
2850}
2851
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002852static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2853{
2854 int ret = 0;
2855 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002856
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002857 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002858 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002859 return -EINVAL;
2860 }
2861
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302862 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002863
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002864 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2865 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302866 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002867 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002868 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2869 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302870 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002871 }
2872
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002873 ALOGV("%s new encoder delay %u and padding %u", __func__,
2874 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2875
2876 return 0;
2877}
2878
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002879static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2880{
2881 return out == adev->primary_output || out == adev->voice_tx_output;
2882}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002883
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302884// note: this call is safe only if the stream_cb is
2885// removed first in close_output_stream (as is done now).
2886static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2887{
2888 if (!stream || !parms)
2889 return;
2890
2891 struct stream_out *out = (struct stream_out *)stream;
2892 struct audio_device *adev = out->dev;
2893
2894 card_status_t status;
2895 int card;
2896 if (parse_snd_card_status(parms, &card, &status) < 0)
2897 return;
2898
2899 pthread_mutex_lock(&adev->lock);
2900 bool valid_cb = (card == adev->snd_card);
2901 pthread_mutex_unlock(&adev->lock);
2902
2903 if (!valid_cb)
2904 return;
2905
2906 lock_output_stream(out);
2907 if (out->card_status != status)
2908 out->card_status = status;
2909 pthread_mutex_unlock(&out->lock);
2910
2911 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
2912 use_case_table[out->usecase],
2913 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2914
2915 if (status == CARD_STATUS_OFFLINE)
2916 out_on_error(stream);
2917
2918 return;
2919}
2920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2922{
2923 struct stream_out *out = (struct stream_out *)stream;
2924 struct audio_device *adev = out->dev;
2925 struct str_parms *parms;
2926 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002927 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928
sangwoobc677242013-08-08 16:53:43 +09002929 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002930 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302932 if (!parms)
2933 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002934 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2935 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002937 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002938 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002940 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002941 * When HDMI cable is unplugged the music playback is paused and
2942 * the policy manager sends routing=0. But the audioflinger continues
2943 * to write data until standby time (3sec). As the HDMI core is
2944 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 * Avoid this by routing audio to speaker until standby.
2946 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002947 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2948 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302949 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002950 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2951 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002952 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302953 /*
2954 * When A2DP is disconnected the
2955 * music playback is paused and the policy manager sends routing=0
2956 * But the audioflingercontinues to write data until standby time
2957 * (3sec). As BT is turned off, the write gets blocked.
2958 * Avoid this by routing audio to speaker until standby.
2959 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002960 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302961 (val == AUDIO_DEVICE_NONE)) {
2962 val = AUDIO_DEVICE_OUT_SPEAKER;
2963 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302964 /* To avoid a2dp to sco overlapping / BT device improper state
2965 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302966 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302967 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2968 if (!audio_extn_a2dp_is_ready()) {
2969 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2970 //combo usecase just by pass a2dp
2971 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2972 val = AUDIO_DEVICE_OUT_SPEAKER;
2973 } else {
2974 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2975 /* update device to a2dp and don't route as BT returned error
2976 * However it is still possible a2dp routing called because
2977 * of current active device disconnection (like wired headset)
2978 */
2979 out->devices = val;
2980 pthread_mutex_unlock(&out->lock);
2981 pthread_mutex_unlock(&adev->lock);
2982 goto error;
2983 }
2984 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002986 /*
2987 * select_devices() call below switches all the usecases on the same
2988 * backend to the new device. Refer to check_usecases_codec_backend() in
2989 * the select_devices(). But how do we undo this?
2990 *
2991 * For example, music playback is active on headset (deep-buffer usecase)
2992 * and if we go to ringtones and select a ringtone, low-latency usecase
2993 * will be started on headset+speaker. As we can't enable headset+speaker
2994 * and headset devices at the same time, select_devices() switches the music
2995 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2996 * So when the ringtone playback is completed, how do we undo the same?
2997 *
2998 * We are relying on the out_set_parameters() call on deep-buffer output,
2999 * once the ringtone playback is ended.
3000 * NOTE: We should not check if the current devices are same as new devices.
3001 * Because select_devices() must be called to switch back the music
3002 * playback to headset.
3003 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003004 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003005 audio_devices_t new_dev = val;
3006 bool same_dev = out->devices == new_dev;
3007 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003008
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003009 if (output_drives_call(adev, out)) {
3010 if(!voice_is_in_call(adev)) {
3011 if (adev->mode == AUDIO_MODE_IN_CALL) {
3012 adev->current_call_output = out;
3013 ret = voice_start_call(adev);
3014 }
3015 } else {
3016 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003017 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003018 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003019 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003020
3021 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003022 if (!same_dev) {
3023 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303024 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3025 adev->perf_lock_opts,
3026 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003027 if (adev->adm_on_routing_change)
3028 adev->adm_on_routing_change(adev->adm_data,
3029 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003030 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003031 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05303032 if (!same_dev)
3033 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003034 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003035 }
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003038 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003040
3041 if (out == adev->primary_output) {
3042 pthread_mutex_lock(&adev->lock);
3043 audio_extn_set_parameters(adev, parms);
3044 pthread_mutex_unlock(&adev->lock);
3045 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003046 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003047 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003048 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003049
3050 audio_extn_dts_create_state_notifier_node(out->usecase);
3051 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3052 popcount(out->channel_mask),
3053 out->playback_started);
3054
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003055 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003056 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003057
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303058 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3059 if (err >= 0) {
3060 strlcpy(out->profile, value, sizeof(out->profile));
3061 ALOGV("updating stream profile with value '%s'", out->profile);
3062 lock_output_stream(out);
3063 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3064 &adev->streams_output_cfg_list,
3065 out->devices, out->flags, out->format,
3066 out->sample_rate, out->bit_width,
3067 out->channel_mask, out->profile,
3068 &out->app_type_cfg);
3069 pthread_mutex_unlock(&out->lock);
3070 }
3071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303073error:
Eric Laurent994a6932013-07-17 11:51:42 -07003074 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 return ret;
3076}
3077
3078static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3079{
3080 struct stream_out *out = (struct stream_out *)stream;
3081 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003082 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 char value[256];
3084 struct str_parms *reply = str_parms_create();
3085 size_t i, j;
3086 int ret;
3087 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003088
3089 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003090 if (reply) {
3091 str_parms_destroy(reply);
3092 }
3093 if (query) {
3094 str_parms_destroy(query);
3095 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003096 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3097 return NULL;
3098 }
3099
Eric Laurent994a6932013-07-17 11:51:42 -07003100 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3102 if (ret >= 0) {
3103 value[0] = '\0';
3104 i = 0;
3105 while (out->supported_channel_masks[i] != 0) {
3106 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3107 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3108 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003109 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003111 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 first = false;
3113 break;
3114 }
3115 }
3116 i++;
3117 }
3118 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3119 str = str_parms_to_str(reply);
3120 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003121 voice_extn_out_get_parameters(out, query, reply);
3122 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08003123 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08003124 free(str);
3125 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003128
Alexy Joseph62142aa2015-11-16 15:10:34 -08003129
3130 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3131 if (ret >= 0) {
3132 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303133 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3134 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003135 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303136 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003137 } else {
3138 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303139 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003140 }
3141 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003142 if (str)
3143 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003144 str = str_parms_to_str(reply);
3145 }
3146
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003147 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3148 if (ret >= 0) {
3149 value[0] = '\0';
3150 i = 0;
3151 first = true;
3152 while (out->supported_formats[i] != 0) {
3153 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3154 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3155 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003156 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 }
3158 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3159 first = false;
3160 break;
3161 }
3162 }
3163 i++;
3164 }
3165 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003166 if (str)
3167 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003168 str = str_parms_to_str(reply);
3169 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003170
3171 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3172 if (ret >= 0) {
3173 value[0] = '\0';
3174 i = 0;
3175 first = true;
3176 while (out->supported_sample_rates[i] != 0) {
3177 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3178 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3179 if (!first) {
3180 strlcat(value, "|", sizeof(value));
3181 }
3182 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3183 first = false;
3184 break;
3185 }
3186 }
3187 i++;
3188 }
3189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3190 if (str)
3191 free(str);
3192 str = str_parms_to_str(reply);
3193 }
3194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 str_parms_destroy(query);
3196 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003197 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 return str;
3199}
3200
3201static uint32_t out_get_latency(const struct audio_stream_out *stream)
3202{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003203 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003205 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206
Alexy Josephaa54c872014-12-03 02:46:47 -08003207 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303208 lock_output_stream(out);
3209 latency = audio_extn_utils_compress_get_dsp_latency(out);
3210 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003211 } else if (out->realtime) {
3212 // since the buffer won't be filled up faster than realtime,
3213 // return a smaller number
3214 if (out->config.rate)
3215 period_ms = (out->af_period_multiplier * out->config.period_size *
3216 1000) / (out->config.rate);
3217 else
3218 period_ms = 0;
3219 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003220 } else {
3221 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003223 }
3224
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003225 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3226 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3227 latency += audio_extn_a2dp_get_encoder_latency();
3228
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303229 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003230 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231}
3232
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303233static float AmpToDb(float amplification)
3234{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303235 float db = DSD_VOLUME_MIN_DB;
3236 if (amplification > 0) {
3237 db = 20 * log10(amplification);
3238 if(db < DSD_VOLUME_MIN_DB)
3239 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303240 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303241 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303242}
3243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244static int out_set_volume(struct audio_stream_out *stream, float left,
3245 float right)
3246{
Eric Laurenta9024de2013-04-04 09:19:12 -07003247 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 int volume[2];
3249
Eric Laurenta9024de2013-04-04 09:19:12 -07003250 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3251 /* only take left channel into account: the API is for stereo anyway */
3252 out->muted = (left == 0.0f);
3253 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003254 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303255 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003256 /*
3257 * Set mute or umute on HDMI passthrough stream.
3258 * Only take left channel into account.
3259 * Mute is 0 and unmute 1
3260 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303261 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303262 } else if (out->format == AUDIO_FORMAT_DSD){
3263 char mixer_ctl_name[128] = "DSD Volume";
3264 struct audio_device *adev = out->dev;
3265 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3266
3267 if (!ctl) {
3268 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3269 __func__, mixer_ctl_name);
3270 return -EINVAL;
3271 }
3272 volume[0] = (int)(AmpToDb(left));
3273 volume[1] = (int)(AmpToDb(right));
3274 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3275 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003276 } else {
3277 char mixer_ctl_name[128];
3278 struct audio_device *adev = out->dev;
3279 struct mixer_ctl *ctl;
3280 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003281 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003283 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3284 "Compress Playback %d Volume", pcm_device_id);
3285 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3286 if (!ctl) {
3287 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3288 __func__, mixer_ctl_name);
3289 return -EINVAL;
3290 }
3291 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3292 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3293 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3294 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003296 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 return -ENOSYS;
3299}
3300
3301static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3302 size_t bytes)
3303{
3304 struct stream_out *out = (struct stream_out *)stream;
3305 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003306 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003308 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303309
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303310 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003311
Dhananjay Kumarac341582017-02-23 23:42:25 +05303312 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303313 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303314 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3315 pthread_mutex_unlock(&out->lock);
3316 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303317 } else {
3318 /* increase written size during SSR to avoid mismatch
3319 * with the written frames count in AF
3320 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003321 // bytes per frame
3322 size_t bpf = audio_bytes_per_sample(out->format) *
3323 audio_channel_count_from_out_mask(out->channel_mask);
3324 if (bpf != 0)
3325 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303326 ALOGD(" %s: sound card is not active/SSR state", __func__);
3327 ret= -EIO;
3328 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303329 }
3330 }
3331
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303332 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303333 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3334 if (audio_bytes_per_sample(out->format) != 0)
3335 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3336 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303337 goto exit;
3338 }
3339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003341 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003342 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003343 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3344 ret = voice_extn_compress_voip_start_output_stream(out);
3345 else
3346 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003347 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003350 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 goto exit;
3352 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303353 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003354 if (last_known_cal_step != -1) {
3355 ALOGD("%s: retry previous failed cal level set", __func__);
3356 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3357 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359
Ashish Jain81eb2a82015-05-13 10:52:34 +05303360 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003361 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303362 adev->is_channel_status_set = true;
3363 }
3364
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003365 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003366 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003367 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003368 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003369 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3370 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303371 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3372 ALOGD("copl(%p):send next track params in gapless", out);
3373 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3374 out->send_next_track_params = false;
3375 out->is_compr_metadata_avail = false;
3376 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003377 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303378 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303379 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003380
Ashish Jain83a6cc22016-06-28 14:34:17 +05303381 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303382 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303383 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303384 pthread_mutex_unlock(&out->lock);
3385 return -EINVAL;
3386 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303387 audio_format_t dst_format = out->hal_op_format;
3388 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303389
3390 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3391 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3392
Ashish Jain83a6cc22016-06-28 14:34:17 +05303393 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303394 dst_format,
3395 buffer,
3396 src_format,
3397 frames);
3398
Ashish Jain83a6cc22016-06-28 14:34:17 +05303399 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303400 bytes_to_write);
3401
3402 /*Convert written bytes in audio flinger format*/
3403 if (ret > 0)
3404 ret = ((ret * format_to_bitwidth_table[out->format]) /
3405 format_to_bitwidth_table[dst_format]);
3406 }
3407 } else
3408 ret = compress_write(out->compr, buffer, bytes);
3409
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303410 if (ret < 0)
3411 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303412 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303413 /*msg to cb thread only if non blocking write is enabled*/
3414 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303415 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303417 } else if (-ENETRESET == ret) {
3418 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303419 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303420 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303421 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003422 }
Ashish Jain5106d362016-05-11 19:23:33 +05303423 if ( ret == (ssize_t)bytes && !out->non_blocking)
3424 out->written += bytes;
3425
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303426 /* Call compr start only when non-zero bytes of data is there to be rendered */
3427 if (!out->playback_started && ret > 0) {
3428 int status = compress_start(out->compr);
3429 if (status < 0) {
3430 ret = status;
3431 ALOGE("%s: compr start failed with err %d", __func__, errno);
3432 goto exit;
3433 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003434 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 out->playback_started = 1;
3436 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003437
3438 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3439 popcount(out->channel_mask),
3440 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 }
3442 pthread_mutex_unlock(&out->lock);
3443 return ret;
3444 } else {
3445 if (out->pcm) {
3446 if (out->muted)
3447 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003448
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303449 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003450
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003451 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003452
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003453 if (out->config.rate)
3454 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3455 out->config.rate;
3456
3457 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3458
3459 request_out_focus(out, ns);
3460
3461 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003463 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303464 out->convert_buffer != NULL) {
3465
3466 memcpy_by_audio_format(out->convert_buffer,
3467 out->hal_op_format,
3468 buffer,
3469 out->hal_ip_format,
3470 out->config.period_size * out->config.channels);
3471
3472 ret = pcm_write(out->pcm, out->convert_buffer,
3473 (out->config.period_size *
3474 out->config.channels *
3475 format_to_bitwidth_table[out->hal_op_format]));
3476 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303477 /*
3478 * To avoid underrun in DSP when the application is not pumping
3479 * data at required rate, check for the no. of bytes and ignore
3480 * pcm_write if it is less than actual buffer size.
3481 * It is a work around to a change in compress VOIP driver.
3482 */
3483 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3484 bytes < (out->config.period_size * out->config.channels *
3485 audio_bytes_per_sample(out->format))) {
3486 size_t voip_buf_size =
3487 out->config.period_size * out->config.channels *
3488 audio_bytes_per_sample(out->format);
3489 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3490 __func__, bytes, voip_buf_size);
3491 usleep(((uint64_t)voip_buf_size - bytes) *
3492 1000000 / audio_stream_out_frame_size(stream) /
3493 out_get_sample_rate(&out->stream.common));
3494 ret = 0;
3495 } else
3496 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303497 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003498
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003499 release_out_focus(out);
3500
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303501 if (ret < 0)
3502 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303503 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3504 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3505 else
3506 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 }
3509
3510exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303511 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303512 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 pthread_mutex_unlock(&out->lock);
3515
3516 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003517 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003518 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303519 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303520 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303521 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303522 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303523 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303524 out->standby = true;
3525 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303526 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303527 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3528 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3529 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 }
3531 return bytes;
3532}
3533
3534static int out_get_render_position(const struct audio_stream_out *stream,
3535 uint32_t *dsp_frames)
3536{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003537 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003538
3539 if (dsp_frames == NULL)
3540 return -EINVAL;
3541
3542 *dsp_frames = 0;
3543 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003544 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303545
3546 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3547 * this operation and adev_close_output_stream(where out gets reset).
3548 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303549 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303550 *dsp_frames = get_actual_pcm_frames_rendered(out);
3551 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3552 return 0;
3553 }
3554
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003555 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303556 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303557 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303559 if (ret < 0)
3560 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003561 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303562 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303564 if (-ENETRESET == ret) {
3565 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303566 out->card_status = CARD_STATUS_OFFLINE;
3567 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303568 } else if(ret < 0) {
3569 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303570 ret = -EINVAL;
3571 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303572 /*
3573 * Handle corner case where compress session is closed during SSR
3574 * and timestamp is queried
3575 */
3576 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303577 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303578 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303579 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303580 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303581 pthread_mutex_unlock(&out->lock);
3582 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003583 } else if (audio_is_linear_pcm(out->format)) {
3584 *dsp_frames = out->written;
3585 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 } else
3587 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588}
3589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003590static int out_add_audio_effect(const struct audio_stream *stream __unused,
3591 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592{
3593 return 0;
3594}
3595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003596static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3597 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598{
3599 return 0;
3600}
3601
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003602static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3603 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604{
3605 return -EINVAL;
3606}
3607
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003608static int out_get_presentation_position(const struct audio_stream_out *stream,
3609 uint64_t *frames, struct timespec *timestamp)
3610{
3611 struct stream_out *out = (struct stream_out *)stream;
3612 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003613 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003614
Ashish Jain5106d362016-05-11 19:23:33 +05303615 /* below piece of code is not guarded against any lock because audioFliner serializes
3616 * this operation and adev_close_output_stream( where out gets reset).
3617 */
3618 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303619 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303620 *frames = get_actual_pcm_frames_rendered(out);
3621 /* this is the best we can do */
3622 clock_gettime(CLOCK_MONOTONIC, timestamp);
3623 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3624 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3625 return 0;
3626 }
3627
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003628 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003629
Ashish Jain5106d362016-05-11 19:23:33 +05303630 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3631 ret = compress_get_tstamp(out->compr, &dsp_frames,
3632 &out->sample_rate);
3633 ALOGVV("%s rendered frames %ld sample_rate %d",
3634 __func__, dsp_frames, out->sample_rate);
3635 *frames = dsp_frames;
3636 if (ret < 0)
3637 ret = -errno;
3638 if (-ENETRESET == ret) {
3639 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303640 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303641 ret = -EINVAL;
3642 } else
3643 ret = 0;
3644 /* this is the best we can do */
3645 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003646 } else {
3647 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003648 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003649 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3650 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003651 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003652 // This adjustment accounts for buffering after app processor.
3653 // It is based on estimated DSP latency per use case, rather than exact.
3654 signed_frames -=
3655 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3656
Eric Laurent949a0892013-09-20 09:20:13 -07003657 // It would be unusual for this value to be negative, but check just in case ...
3658 if (signed_frames >= 0) {
3659 *frames = signed_frames;
3660 ret = 0;
3661 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003662 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303663 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303664 *frames = out->written;
3665 clock_gettime(CLOCK_MONOTONIC, timestamp);
3666 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003667 }
3668 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003669 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003670 return ret;
3671}
3672
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673static int out_set_callback(struct audio_stream_out *stream,
3674 stream_callback_t callback, void *cookie)
3675{
3676 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003677 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678
3679 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003680 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003681 out->client_callback = callback;
3682 out->client_cookie = cookie;
3683 if (out->adsp_hdlr_stream_handle) {
3684 ret = audio_extn_adsp_hdlr_stream_set_callback(
3685 out->adsp_hdlr_stream_handle,
3686 callback,
3687 cookie);
3688 if (ret)
3689 ALOGW("%s:adsp hdlr callback registration failed %d",
3690 __func__, ret);
3691 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003692 pthread_mutex_unlock(&out->lock);
3693 return 0;
3694}
3695
3696static int out_pause(struct audio_stream_out* stream)
3697{
3698 struct stream_out *out = (struct stream_out *)stream;
3699 int status = -ENOSYS;
3700 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003701 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003702 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003703 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003704 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303705 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303706 status = compress_pause(out->compr);
3707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003708 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003709
Mingming Yin21854652016-04-13 11:54:02 -07003710 if (audio_extn_passthru_is_active()) {
3711 ALOGV("offload use case, pause passthru");
3712 audio_extn_passthru_on_pause(out);
3713 }
3714
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303715 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003716 audio_extn_dts_notify_playback_state(out->usecase, 0,
3717 out->sample_rate, popcount(out->channel_mask),
3718 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 }
3720 pthread_mutex_unlock(&out->lock);
3721 }
3722 return status;
3723}
3724
3725static int out_resume(struct audio_stream_out* stream)
3726{
3727 struct stream_out *out = (struct stream_out *)stream;
3728 int status = -ENOSYS;
3729 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003730 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003731 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003732 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003733 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003734 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303735 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303736 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003737 }
3738 if (!status) {
3739 out->offload_state = OFFLOAD_STATE_PLAYING;
3740 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303741 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003742 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3743 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003744 }
3745 pthread_mutex_unlock(&out->lock);
3746 }
3747 return status;
3748}
3749
3750static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3751{
3752 struct stream_out *out = (struct stream_out *)stream;
3753 int status = -ENOSYS;
3754 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003755 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003756 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3758 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3759 else
3760 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3761 pthread_mutex_unlock(&out->lock);
3762 }
3763 return status;
3764}
3765
3766static int out_flush(struct audio_stream_out* stream)
3767{
3768 struct stream_out *out = (struct stream_out *)stream;
3769 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003770 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003771 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003772 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003773 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3774 stop_compressed_output_l(out);
3775 out->written = 0;
3776 } else {
3777 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3778 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003779 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003780 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003781 return 0;
3782 }
3783 return -ENOSYS;
3784}
3785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786/** audio_stream_in implementation **/
3787static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3788{
3789 struct stream_in *in = (struct stream_in *)stream;
3790
3791 return in->config.rate;
3792}
3793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003794static int in_set_sample_rate(struct audio_stream *stream __unused,
3795 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796{
3797 return -ENOSYS;
3798}
3799
3800static size_t in_get_buffer_size(const struct audio_stream *stream)
3801{
3802 struct stream_in *in = (struct stream_in *)stream;
3803
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003804 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3805 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003806 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3807 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303808 else if(audio_extn_cin_attached_usecase(in->usecase))
3809 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003810
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003811 return in->config.period_size * in->af_period_multiplier *
3812 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813}
3814
3815static uint32_t in_get_channels(const struct audio_stream *stream)
3816{
3817 struct stream_in *in = (struct stream_in *)stream;
3818
3819 return in->channel_mask;
3820}
3821
3822static audio_format_t in_get_format(const struct audio_stream *stream)
3823{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003824 struct stream_in *in = (struct stream_in *)stream;
3825
3826 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827}
3828
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003829static int in_set_format(struct audio_stream *stream __unused,
3830 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831{
3832 return -ENOSYS;
3833}
3834
3835static int in_standby(struct audio_stream *stream)
3836{
3837 struct stream_in *in = (struct stream_in *)stream;
3838 struct audio_device *adev = in->dev;
3839 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303840 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3841 stream, in->usecase, use_case_table[in->usecase]);
3842
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003843 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003844 if (!in->standby && in->is_st_session) {
3845 ALOGD("%s: sound trigger pcm stop lab", __func__);
3846 audio_extn_sound_trigger_stop_lab(in);
3847 in->standby = 1;
3848 }
3849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003851 if (adev->adm_deregister_stream)
3852 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3853
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003856 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3857 voice_extn_compress_voip_close_input_stream(stream);
3858 ALOGD("VOIP input entered standby");
3859 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303860 if (audio_extn_cin_attached_usecase(in->usecase))
3861 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003862 if (in->pcm) {
3863 pcm_close(in->pcm);
3864 in->pcm = NULL;
3865 }
3866 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003867 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003868 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 }
3870 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003871 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 return status;
3873}
3874
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003875static int in_dump(const struct audio_stream *stream __unused,
3876 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877{
3878 return 0;
3879}
3880
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303881static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3882{
3883 if (!stream || !parms)
3884 return;
3885
3886 struct stream_in *in = (struct stream_in *)stream;
3887 struct audio_device *adev = in->dev;
3888
3889 card_status_t status;
3890 int card;
3891 if (parse_snd_card_status(parms, &card, &status) < 0)
3892 return;
3893
3894 pthread_mutex_lock(&adev->lock);
3895 bool valid_cb = (card == adev->snd_card);
3896 pthread_mutex_unlock(&adev->lock);
3897
3898 if (!valid_cb)
3899 return;
3900
3901 lock_input_stream(in);
3902 if (in->card_status != status)
3903 in->card_status = status;
3904 pthread_mutex_unlock(&in->lock);
3905
3906 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3907 use_case_table[in->usecase],
3908 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3909
3910 // a better solution would be to report error back to AF and let
3911 // it put the stream to standby
3912 if (status == CARD_STATUS_OFFLINE)
3913 in_standby(&in->stream.common);
3914
3915 return;
3916}
3917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3919{
3920 struct stream_in *in = (struct stream_in *)stream;
3921 struct audio_device *adev = in->dev;
3922 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003924 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303926 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 parms = str_parms_create_str(kvpairs);
3928
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303929 if (!parms)
3930 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003931 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003932 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003933
3934 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3935 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 val = atoi(value);
3937 /* no audio source uses val == 0 */
3938 if ((in->source != val) && (val != 0)) {
3939 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003940 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3941 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3942 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003943 (in->config.rate == 8000 || in->config.rate == 16000 ||
3944 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003945 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003946 err = voice_extn_compress_voip_open_input_stream(in);
3947 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003948 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003949 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003950 }
3951 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 }
3953 }
3954
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003955 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3956 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003958 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 in->device = val;
3960 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003961 if (!in->standby && !in->is_st_session) {
3962 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003963 if (adev->adm_on_routing_change)
3964 adev->adm_on_routing_change(adev->adm_data,
3965 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003966 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968 }
3969 }
3970
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303971 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3972 if (err >= 0) {
3973 strlcpy(in->profile, value, sizeof(in->profile));
3974 ALOGV("updating stream profile with value '%s'", in->profile);
3975 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3976 &adev->streams_input_cfg_list,
3977 in->device, in->flags, in->format,
3978 in->sample_rate, in->bit_width,
3979 in->profile, &in->app_type_cfg);
3980 }
3981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003983 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984
3985 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303986error:
Eric Laurent994a6932013-07-17 11:51:42 -07003987 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 return ret;
3989}
3990
3991static char* in_get_parameters(const struct audio_stream *stream,
3992 const char *keys)
3993{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003994 struct stream_in *in = (struct stream_in *)stream;
3995 struct str_parms *query = str_parms_create_str(keys);
3996 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003997 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003998
3999 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004000 if (reply) {
4001 str_parms_destroy(reply);
4002 }
4003 if (query) {
4004 str_parms_destroy(query);
4005 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004006 ALOGE("in_get_parameters: failed to create query or reply");
4007 return NULL;
4008 }
4009
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004010 ALOGV("%s: enter: keys - %s", __func__, keys);
4011
4012 voice_extn_in_get_parameters(in, query, reply);
4013
4014 str = str_parms_to_str(reply);
4015 str_parms_destroy(query);
4016 str_parms_destroy(reply);
4017
4018 ALOGV("%s: exit: returns - %s", __func__, str);
4019 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020}
4021
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004022static int in_set_gain(struct audio_stream_in *stream __unused,
4023 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024{
4025 return 0;
4026}
4027
4028static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4029 size_t bytes)
4030{
4031 struct stream_in *in = (struct stream_in *)stream;
4032 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304033 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304034 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004036 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304037
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004038 if (in->is_st_session) {
4039 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4040 /* Read from sound trigger HAL */
4041 audio_extn_sound_trigger_read(in, buffer, bytes);
4042 pthread_mutex_unlock(&in->lock);
4043 return bytes;
4044 }
4045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004047 pthread_mutex_lock(&adev->lock);
4048 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4049 ret = voice_extn_compress_voip_start_input_stream(in);
4050 else
4051 ret = start_input_stream(in);
4052 pthread_mutex_unlock(&adev->lock);
4053 if (ret != 0) {
4054 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 }
4056 in->standby = 0;
4057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004059 // what's the duration requested by the client?
4060 long ns = 0;
4061
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304062 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004063 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4064 in->config.rate;
4065
4066 request_in_focus(in, ns);
4067 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004068
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304069 if (audio_extn_cin_attached_usecase(in->usecase)) {
4070 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4071 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304072 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004073 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304074 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004075 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004076 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004077 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304078 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004079 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304080 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4081 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4082 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4083 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304084 ret = -EINVAL;
4085 goto exit;
4086 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304087 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304088 ret = -errno;
4089 }
4090 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304091 /* bytes read is always set to bytes for non compress usecases */
4092 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 }
4094
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004095 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097 /*
4098 * Instead of writing zeroes here, we could trust the hardware
4099 * to always provide zeroes when muted.
4100 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304101 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4102 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 memset(buffer, 0, bytes);
4104
4105exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004106 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304107 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 pthread_mutex_unlock(&in->lock);
4109
4110 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304111 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304112 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304113 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304114 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304115 in->standby = true;
4116 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304117 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4118 bytes_read = bytes;
4119 memset(buffer, 0, bytes);
4120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004122 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304123 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304124 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304126 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127}
4128
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004129static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130{
4131 return 0;
4132}
4133
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004134static int add_remove_audio_effect(const struct audio_stream *stream,
4135 effect_handle_t effect,
4136 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004138 struct stream_in *in = (struct stream_in *)stream;
4139 int status = 0;
4140 effect_descriptor_t desc;
4141
4142 status = (*effect)->get_descriptor(effect, &desc);
4143 if (status != 0)
4144 return status;
4145
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004146 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004147 pthread_mutex_lock(&in->dev->lock);
4148 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4149 in->enable_aec != enable &&
4150 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4151 in->enable_aec = enable;
4152 if (!in->standby)
4153 select_devices(in->dev, in->usecase);
4154 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004155 if (in->enable_ns != enable &&
4156 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4157 in->enable_ns = enable;
4158 if (!in->standby)
4159 select_devices(in->dev, in->usecase);
4160 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004161 pthread_mutex_unlock(&in->dev->lock);
4162 pthread_mutex_unlock(&in->lock);
4163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 return 0;
4165}
4166
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004167static int in_add_audio_effect(const struct audio_stream *stream,
4168 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169{
Eric Laurent994a6932013-07-17 11:51:42 -07004170 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004171 return add_remove_audio_effect(stream, effect, true);
4172}
4173
4174static int in_remove_audio_effect(const struct audio_stream *stream,
4175 effect_handle_t effect)
4176{
Eric Laurent994a6932013-07-17 11:51:42 -07004177 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004178 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179}
4180
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304181int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 audio_io_handle_t handle,
4183 audio_devices_t devices,
4184 audio_output_flags_t flags,
4185 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004186 struct audio_stream_out **stream_out,
4187 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188{
4189 struct audio_device *adev = (struct audio_device *)dev;
4190 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304191 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004192 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004193 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4198
Mingming Yin3a941d42016-02-17 18:08:05 -08004199 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4200 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304201 devices, flags, &out->stream);
4202
4203
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004204 if (!out) {
4205 return -ENOMEM;
4206 }
4207
Haynes Mathew George204045b2015-02-25 20:32:03 -08004208 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004209 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004210 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 if (devices == AUDIO_DEVICE_NONE)
4213 devices = AUDIO_DEVICE_OUT_SPEAKER;
4214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 out->flags = flags;
4216 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004217 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004218 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004219 out->sample_rate = config->sample_rate;
4220 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4221 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004222 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004223 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004224 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304225 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304226 out->started = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227
Mingming Yin3a941d42016-02-17 18:08:05 -08004228 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4229 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4230 pthread_mutex_lock(&adev->lock);
4231 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4232 ret = read_hdmi_sink_caps(out);
4233 pthread_mutex_unlock(&adev->lock);
4234 if (ret != 0) {
4235 if (ret == -ENOSYS) {
4236 /* ignore and go with default */
4237 ret = 0;
4238 } else {
4239 ALOGE("error reading hdmi sink caps");
4240 goto error_open;
4241 }
4242 }
4243 }
4244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304246 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004247 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004248 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004249 ret = voice_extn_compress_voip_open_output_stream(out);
4250 if (ret != 0) {
4251 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4252 __func__, ret);
4253 goto error_open;
4254 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004255 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304256 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304257 pthread_mutex_lock(&adev->lock);
4258 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4259 pthread_mutex_unlock(&adev->lock);
4260
4261 // reject offload during card offline to allow
4262 // fallback to s/w paths
4263 if (offline) {
4264 ret = -ENODEV;
4265 goto error_open;
4266 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004268 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4269 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4270 ALOGE("%s: Unsupported Offload information", __func__);
4271 ret = -EINVAL;
4272 goto error_open;
4273 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004274
Mingming Yin3a941d42016-02-17 18:08:05 -08004275 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004276 if(config->offload_info.format == 0)
4277 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004278 if (config->offload_info.sample_rate == 0)
4279 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004280 }
4281
Mingming Yin90310102013-11-13 16:57:00 -08004282 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304283 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004284 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004285 ret = -EINVAL;
4286 goto error_open;
4287 }
4288
4289 out->compr_config.codec = (struct snd_codec *)
4290 calloc(1, sizeof(struct snd_codec));
4291
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004292 if (!out->compr_config.codec) {
4293 ret = -ENOMEM;
4294 goto error_open;
4295 }
4296
Dhananjay Kumarac341582017-02-23 23:42:25 +05304297 out->stream.pause = out_pause;
4298 out->stream.resume = out_resume;
4299 out->stream.flush = out_flush;
4300 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004301 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004302 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304303 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004304 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304305 } else {
4306 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4307 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004308 }
vivek mehta446c3962015-09-14 10:57:35 -07004309
4310 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004311 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4312 config->format == 0 && config->sample_rate == 0 &&
4313 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004314 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004315 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4316 } else {
4317 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4318 ret = -EEXIST;
4319 goto error_open;
4320 }
vivek mehta446c3962015-09-14 10:57:35 -07004321 }
4322
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004323 if (config->offload_info.channel_mask)
4324 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004325 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004326 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004327 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004328 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304329 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004330 ret = -EINVAL;
4331 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004332 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004333
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004334 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004335 out->sample_rate = config->offload_info.sample_rate;
4336
Mingming Yin3ee55c62014-08-04 14:23:35 -07004337 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004338
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304339 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4340 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4341 audio_extn_dolby_send_ddp_endp_params(adev);
4342 audio_extn_dolby_set_dmid(adev);
4343 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004346 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004347 out->compr_config.codec->bit_rate =
4348 config->offload_info.bit_rate;
4349 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304350 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004351 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304352 /* Update bit width only for non passthrough usecases.
4353 * For passthrough usecases, the output will always be opened @16 bit
4354 */
4355 if (!audio_extn_passthru_is_passthrough_stream(out))
4356 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304357
4358 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4359 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4360 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4361
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004362 /*TODO: Do we need to change it for passthrough */
4363 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364
Manish Dewangana6fc5442015-08-24 20:30:31 +05304365 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4366 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304367 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304368 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304369 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4370 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304371
4372 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4373 AUDIO_FORMAT_PCM) {
4374
4375 /*Based on platform support, configure appropriate alsa format for corresponding
4376 *hal input format.
4377 */
4378 out->compr_config.codec->format = hal_format_to_alsa(
4379 config->offload_info.format);
4380
Ashish Jain83a6cc22016-06-28 14:34:17 +05304381 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304382 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304383 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304384
Dhananjay Kumarac341582017-02-23 23:42:25 +05304385 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304386 *hal input format and alsa format might differ based on platform support.
4387 */
4388 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304389 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304390
4391 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4392
4393 /* Check if alsa session is configured with the same format as HAL input format,
4394 * if not then derive correct fragment size needed to accomodate the
4395 * conversion of HAL input format to alsa format.
4396 */
4397 audio_extn_utils_update_direct_pcm_fragment_size(out);
4398
4399 /*if hal input and output fragment size is different this indicates HAL input format is
4400 *not same as the alsa format
4401 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304402 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304403 /*Allocate a buffer to convert input data to the alsa configured format.
4404 *size of convert buffer is equal to the size required to hold one fragment size
4405 *worth of pcm data, this is because flinger does not write more than fragment_size
4406 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304407 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4408 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304409 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4410 ret = -ENOMEM;
4411 goto error_open;
4412 }
4413 }
4414 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4415 out->compr_config.fragment_size =
4416 audio_extn_passthru_get_buffer_size(&config->offload_info);
4417 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4418 } else {
4419 out->compr_config.fragment_size =
4420 platform_get_compress_offload_buffer_size(&config->offload_info);
4421 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4422 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004423
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304424 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4425 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4426 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004427 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304428 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004429
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304430 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4431 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4432 }
4433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004434 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4435 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004436
Manish Dewangan69426c82017-01-30 17:35:36 +05304437 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4438 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4439 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4440 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4441 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4442 } else {
4443 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4444 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004445
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304446 memset(&out->channel_map_param, 0,
4447 sizeof(struct audio_out_channel_map_param));
4448
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004449 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304450 out->send_next_track_params = false;
4451 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004452 out->offload_state = OFFLOAD_STATE_IDLE;
4453 out->playback_started = 0;
4454
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004455 audio_extn_dts_create_state_notifier_node(out->usecase);
4456
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004457 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4458 __func__, config->offload_info.version,
4459 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304460
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304461 /* Check if DSD audio format is supported in codec
4462 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304463 */
4464
4465 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304466 (!platform_check_codec_dsd_support(adev->platform) ||
4467 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304468 ret = -EINVAL;
4469 goto error_open;
4470 }
4471
Ashish Jain5106d362016-05-11 19:23:33 +05304472 /* Disable gapless if any of the following is true
4473 * passthrough playback
4474 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304475 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304476 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304477 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304478 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004479 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304480 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304481 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304482 check_and_set_gapless_mode(adev, false);
4483 } else
4484 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004485
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304486 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004487 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4488 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304489 if (config->format == AUDIO_FORMAT_DSD) {
4490 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4491 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4492 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004493
4494 create_offload_callback_thread(out);
4495
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004496 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304497 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004498 if (ret != 0) {
4499 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4500 __func__, ret);
4501 goto error_open;
4502 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004503 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4504 if (config->sample_rate == 0)
4505 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4506 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4507 config->sample_rate != 8000) {
4508 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4509 ret = -EINVAL;
4510 goto error_open;
4511 }
4512 out->sample_rate = config->sample_rate;
4513 out->config.rate = config->sample_rate;
4514 if (config->format == AUDIO_FORMAT_DEFAULT)
4515 config->format = AUDIO_FORMAT_PCM_16_BIT;
4516 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4517 config->format = AUDIO_FORMAT_PCM_16_BIT;
4518 ret = -EINVAL;
4519 goto error_open;
4520 }
4521 out->format = config->format;
4522 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4523 out->config = pcm_config_afe_proxy_playback;
4524 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004525 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304526 unsigned int channels = 0;
4527 /*Update config params to default if not set by the caller*/
4528 if (config->sample_rate == 0)
4529 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4530 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4531 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4532 if (config->format == AUDIO_FORMAT_DEFAULT)
4533 config->format = AUDIO_FORMAT_PCM_16_BIT;
4534
4535 channels = audio_channel_count_from_out_mask(out->channel_mask);
4536
Ashish Jain83a6cc22016-06-28 14:34:17 +05304537 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4538 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004539 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4540 out->flags);
4541 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304542 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4543 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4544 out->config = pcm_config_low_latency;
4545 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4546 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4547 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304548 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4549 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4550 if (out->config.period_size <= 0) {
4551 ALOGE("Invalid configuration period size is not valid");
4552 ret = -EINVAL;
4553 goto error_open;
4554 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304555 } else {
4556 /* primary path is the default path selected if no other outputs are available/suitable */
4557 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4558 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4559 }
4560 out->hal_ip_format = format = out->format;
4561 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4562 out->hal_op_format = pcm_format_to_hal(out->config.format);
4563 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4564 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004565 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304566 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304567 if (out->hal_ip_format != out->hal_op_format) {
4568 uint32_t buffer_size = out->config.period_size *
4569 format_to_bitwidth_table[out->hal_op_format] *
4570 out->config.channels;
4571 out->convert_buffer = calloc(1, buffer_size);
4572 if (out->convert_buffer == NULL){
4573 ALOGE("Allocation failed for convert buffer for size %d",
4574 out->compr_config.fragment_size);
4575 ret = -ENOMEM;
4576 goto error_open;
4577 }
4578 ALOGD("Convert buffer allocated of size %d", buffer_size);
4579 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 }
4581
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004582 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4583 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304584
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004585 /* TODO remove this hardcoding and check why width is zero*/
4586 if (out->bit_width == 0)
4587 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304588 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004589 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304590 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304591 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304592 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004593 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4594 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4595 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004596 if(adev->primary_output == NULL)
4597 adev->primary_output = out;
4598 else {
4599 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004600 ret = -EEXIST;
4601 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004602 }
4603 }
4604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 /* Check if this usecase is already existing */
4606 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004607 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4608 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004611 ret = -EEXIST;
4612 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 pthread_mutex_unlock(&adev->lock);
4616
4617 out->stream.common.get_sample_rate = out_get_sample_rate;
4618 out->stream.common.set_sample_rate = out_set_sample_rate;
4619 out->stream.common.get_buffer_size = out_get_buffer_size;
4620 out->stream.common.get_channels = out_get_channels;
4621 out->stream.common.get_format = out_get_format;
4622 out->stream.common.set_format = out_set_format;
4623 out->stream.common.standby = out_standby;
4624 out->stream.common.dump = out_dump;
4625 out->stream.common.set_parameters = out_set_parameters;
4626 out->stream.common.get_parameters = out_get_parameters;
4627 out->stream.common.add_audio_effect = out_add_audio_effect;
4628 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4629 out->stream.get_latency = out_get_latency;
4630 out->stream.set_volume = out_set_volume;
4631 out->stream.write = out_write;
4632 out->stream.get_render_position = out_get_render_position;
4633 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004634 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004636 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004638 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004639 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640
4641 config->format = out->stream.common.get_format(&out->stream.common);
4642 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4643 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4644
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304645 /*
4646 By locking output stream before registering, we allow the callback
4647 to update stream's state only after stream's initial state is set to
4648 adev state.
4649 */
4650 lock_output_stream(out);
4651 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4652 pthread_mutex_lock(&adev->lock);
4653 out->card_status = adev->card_status;
4654 pthread_mutex_unlock(&adev->lock);
4655 pthread_mutex_unlock(&out->lock);
4656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304658 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004659 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004660
4661 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4662 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4663 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004664 /* setup a channel for client <--> adsp communication for stream events */
4665 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004666 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4667 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004668 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4669 out->usecase, PCM_PLAYBACK);
4670 hdlr_stream_cfg.flags = out->flags;
4671 hdlr_stream_cfg.type = PCM_PLAYBACK;
4672 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4673 &hdlr_stream_cfg);
4674 if (ret) {
4675 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4676 out->adsp_hdlr_stream_handle = NULL;
4677 }
4678 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004679 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4680 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4681 if (ret < 0) {
4682 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4683 out->ip_hdlr_handle = NULL;
4684 }
4685 }
Eric Laurent994a6932013-07-17 11:51:42 -07004686 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004688
4689error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304690 if (out->convert_buffer)
4691 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004692 free(out);
4693 *stream_out = NULL;
4694 ALOGD("%s: exit: ret %d", __func__, ret);
4695 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696}
4697
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304698void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 struct audio_stream_out *stream)
4700{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004701 struct stream_out *out = (struct stream_out *)stream;
4702 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004703 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004704
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304705 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4706
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304707 // must deregister from sndmonitor first to prevent races
4708 // between the callback and close_stream
4709 audio_extn_snd_mon_unregister_listener(out);
4710
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004711 /* close adsp hdrl session before standby */
4712 if (out->adsp_hdlr_stream_handle) {
4713 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4714 if (ret)
4715 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4716 out->adsp_hdlr_stream_handle = NULL;
4717 }
4718
Naresh Tanniru85819452017-05-04 18:55:45 -07004719 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4720 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4721 out->ip_hdlr_handle = NULL;
4722 }
4723
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004724 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304725 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004726 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304727 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304728 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004729 if(ret != 0)
4730 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4731 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004732 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004733 out_standby(&stream->common);
4734
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004735 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004736 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004737 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004738 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004739 if (out->compr_config.codec != NULL)
4740 free(out->compr_config.codec);
4741 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004742
Ashish Jain83a6cc22016-06-28 14:34:17 +05304743 if (out->convert_buffer != NULL) {
4744 free(out->convert_buffer);
4745 out->convert_buffer = NULL;
4746 }
4747
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004748 if (adev->voice_tx_output == out)
4749 adev->voice_tx_output = NULL;
4750
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304751 if (adev->primary_output == out)
4752 adev->primary_output = NULL;
4753
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004754 pthread_cond_destroy(&out->cond);
4755 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004757 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758}
4759
4760static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4761{
4762 struct audio_device *adev = (struct audio_device *)dev;
4763 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004765 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004766 int ret;
4767 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004768
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004769 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304772 if (!parms)
4773 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304774
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304775 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
4776 if (ret >= 0) {
4777 /* When set to false, HAL should disable EC and NS */
4778 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4779 adev->bt_sco_on = true;
4780 else
4781 adev->bt_sco_on = false;
4782 }
4783
Naresh Tanniru4c630392014-05-12 01:05:52 +05304784 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004785 status = voice_set_parameters(adev, parms);
4786 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004787 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004789 status = platform_set_parameters(adev->platform, parms);
4790 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004791 goto done;
4792
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004793 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4794 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004795 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4797 adev->bluetooth_nrec = true;
4798 else
4799 adev->bluetooth_nrec = false;
4800 }
4801
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004802 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4803 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4805 adev->screen_off = false;
4806 else
4807 adev->screen_off = true;
4808 }
4809
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004810 ret = str_parms_get_int(parms, "rotation", &val);
4811 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004812 bool reverse_speakers = false;
4813 switch(val) {
4814 // FIXME: note that the code below assumes that the speakers are in the correct placement
4815 // relative to the user when the device is rotated 90deg from its default rotation. This
4816 // assumption is device-specific, not platform-specific like this code.
4817 case 270:
4818 reverse_speakers = true;
4819 break;
4820 case 0:
4821 case 90:
4822 case 180:
4823 break;
4824 default:
4825 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004826 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004827 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004828 if (status == 0) {
4829 if (adev->speaker_lr_swap != reverse_speakers) {
4830 adev->speaker_lr_swap = reverse_speakers;
4831 // only update the selected device if there is active pcm playback
4832 struct audio_usecase *usecase;
4833 struct listnode *node;
4834 list_for_each(node, &adev->usecase_list) {
4835 usecase = node_to_item(node, struct audio_usecase, list);
4836 if (usecase->type == PCM_PLAYBACK) {
4837 select_devices(adev, usecase->id);
4838 break;
4839 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004840 }
4841 }
4842 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004843 }
4844
Mingming Yin514a8bc2014-07-29 15:22:21 -07004845 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4846 if (ret >= 0) {
4847 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4848 adev->bt_wb_speech_enabled = true;
4849 else
4850 adev->bt_wb_speech_enabled = false;
4851 }
4852
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004853 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4854 if (ret >= 0) {
4855 val = atoi(value);
4856 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004857 ALOGV("cache new ext disp type and edid");
4858 ret = platform_get_ext_disp_type(adev->platform);
4859 if (ret < 0) {
4860 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004861 status = ret;
4862 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004863 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004864 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004865 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004866 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004867 /*
4868 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4869 * Per AudioPolicyManager, USB device is higher priority than WFD.
4870 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4871 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4872 * starting voice call on USB
4873 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004874 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4875 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004876 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4877 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004878 }
vivek mehta344576a2016-04-12 18:56:03 -07004879 ALOGV("detected USB connect .. disable proxy");
4880 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004881 }
4882 }
4883
4884 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4885 if (ret >= 0) {
4886 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004887 /*
4888 * The HDMI / Displayport disconnect handling has been moved to
4889 * audio extension to ensure that its parameters are not
4890 * invalidated prior to updating sysfs of the disconnect event
4891 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4892 */
4893 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004894 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004895 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4896 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304897 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4898 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004899 }
vivek mehta344576a2016-04-12 18:56:03 -07004900 ALOGV("detected USB disconnect .. enable proxy");
4901 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004902 }
4903 }
4904
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304905 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4906 if (ret >= 0) {
4907 struct audio_usecase *usecase;
4908 struct listnode *node;
4909 list_for_each(node, &adev->usecase_list) {
4910 usecase = node_to_item(node, struct audio_usecase, list);
4911 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004912 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304913 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08004914
4915 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304916 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08004917 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304918 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304919 //force device switch to re configure encoder
4920 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304921 audio_extn_a2dp_set_handoff_mode(false);
4922 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304923 break;
4924 }
4925 }
4926 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004927
4928 //handle vr audio setparam
4929 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4930 value, sizeof(value));
4931 if (ret >= 0) {
4932 ALOGI("Setting vr mode to be %s", value);
4933 if (!strncmp(value, "true", 4)) {
4934 adev->vr_audio_mode_enabled = true;
4935 ALOGI("Setting vr mode to true");
4936 } else if (!strncmp(value, "false", 5)) {
4937 adev->vr_audio_mode_enabled = false;
4938 ALOGI("Setting vr mode to false");
4939 } else {
4940 ALOGI("wrong vr mode set");
4941 }
4942 }
4943
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304944 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004945done:
4946 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004947 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304948error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004949 ALOGV("%s: exit with code(%d)", __func__, status);
4950 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004951}
4952
4953static char* adev_get_parameters(const struct audio_hw_device *dev,
4954 const char *keys)
4955{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004956 struct audio_device *adev = (struct audio_device *)dev;
4957 struct str_parms *reply = str_parms_create();
4958 struct str_parms *query = str_parms_create_str(keys);
4959 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304960 char value[256] = {0};
4961 int ret = 0;
4962
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004963 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004964 if (reply) {
4965 str_parms_destroy(reply);
4966 }
4967 if (query) {
4968 str_parms_destroy(query);
4969 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004970 ALOGE("adev_get_parameters: failed to create query or reply");
4971 return NULL;
4972 }
4973
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004974 //handle vr audio getparam
4975
4976 ret = str_parms_get_str(query,
4977 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4978 value, sizeof(value));
4979
4980 if (ret >= 0) {
4981 bool vr_audio_enabled = false;
4982 pthread_mutex_lock(&adev->lock);
4983 vr_audio_enabled = adev->vr_audio_mode_enabled;
4984 pthread_mutex_unlock(&adev->lock);
4985
4986 ALOGI("getting vr mode to %d", vr_audio_enabled);
4987
4988 if (vr_audio_enabled) {
4989 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4990 "true");
4991 goto exit;
4992 } else {
4993 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4994 "false");
4995 goto exit;
4996 }
4997 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004998
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004999 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005000 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005001 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005002 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305003 pthread_mutex_unlock(&adev->lock);
5004
Naresh Tannirud7205b62014-06-20 02:54:48 +05305005exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005006 str = str_parms_to_str(reply);
5007 str_parms_destroy(query);
5008 str_parms_destroy(reply);
5009
5010 ALOGV("%s: exit: returns - %s", __func__, str);
5011 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012}
5013
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005014static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015{
5016 return 0;
5017}
5018
5019static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5020{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005021 int ret;
5022 struct audio_device *adev = (struct audio_device *)dev;
5023 pthread_mutex_lock(&adev->lock);
5024 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005025 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005026 pthread_mutex_unlock(&adev->lock);
5027 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028}
5029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005030static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5031 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032{
5033 return -ENOSYS;
5034}
5035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005036static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5037 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005038{
5039 return -ENOSYS;
5040}
5041
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005042static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5043 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044{
5045 return -ENOSYS;
5046}
5047
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005048static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5049 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050{
5051 return -ENOSYS;
5052}
5053
5054static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5055{
5056 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005058 pthread_mutex_lock(&adev->lock);
5059 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005060 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005062 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005063 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005064 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005065 adev->current_call_output = NULL;
5066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005067 }
5068 pthread_mutex_unlock(&adev->lock);
5069 return 0;
5070}
5071
5072static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5073{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005074 int ret;
5075
5076 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005077 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005078 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5079 pthread_mutex_unlock(&adev->lock);
5080
5081 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082}
5083
5084static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5085{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005086 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 return 0;
5088}
5089
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005090static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091 const struct audio_config *config)
5092{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005093 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005095 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5096 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097}
5098
5099static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005100 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005101 audio_devices_t devices,
5102 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005103 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305104 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005105 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005106 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107{
5108 struct audio_device *adev = (struct audio_device *)dev;
5109 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005110 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005111 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005112 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305113 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305116 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5117 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120
5121 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005122
5123 if (!in) {
5124 ALOGE("failed to allocate input stream");
5125 return -ENOMEM;
5126 }
5127
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305128 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305129 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5130 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005131 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005132 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 in->stream.common.get_sample_rate = in_get_sample_rate;
5135 in->stream.common.set_sample_rate = in_set_sample_rate;
5136 in->stream.common.get_buffer_size = in_get_buffer_size;
5137 in->stream.common.get_channels = in_get_channels;
5138 in->stream.common.get_format = in_get_format;
5139 in->stream.common.set_format = in_set_format;
5140 in->stream.common.standby = in_standby;
5141 in->stream.common.dump = in_dump;
5142 in->stream.common.set_parameters = in_set_parameters;
5143 in->stream.common.get_parameters = in_get_parameters;
5144 in->stream.common.add_audio_effect = in_add_audio_effect;
5145 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5146 in->stream.set_gain = in_set_gain;
5147 in->stream.read = in_read;
5148 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5149
5150 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005151 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005152 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005153 in->standby = 1;
5154 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005155 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005156 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305158 in->usecase = USECASE_AUDIO_RECORD;
5159 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5160 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5161 is_low_latency = true;
5162#if LOW_LATENCY_CAPTURE_USE_CASE
5163 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5164#endif
5165 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5166 }
5167
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005168 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005169 if (in->realtime) {
5170 in->config = pcm_config_audio_capture_rt;
5171 in->sample_rate = in->config.rate;
5172 in->af_period_multiplier = af_period_multiplier;
5173 } else {
5174 in->config = pcm_config_audio_capture;
5175 in->config.rate = config->sample_rate;
5176 in->sample_rate = config->sample_rate;
5177 in->af_period_multiplier = 1;
5178 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305179 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305181 /* restrict 24 bit capture for unprocessed source only
5182 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5183 */
5184 if (config->format == AUDIO_FORMAT_DEFAULT) {
5185 config->format = AUDIO_FORMAT_PCM_16_BIT;
5186 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5187 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5188 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5189 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5190 bool ret_error = false;
5191 in->bit_width = 24;
5192 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5193 from HAL is 24_packed and 8_24
5194 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5195 24_packed return error indicating supported format is 24_packed
5196 *> In case of any other source requesting 24 bit or float return error
5197 indicating format supported is 16 bit only.
5198
5199 on error flinger will retry with supported format passed
5200 */
5201 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5202 (source != AUDIO_SOURCE_CAMCORDER)) {
5203 config->format = AUDIO_FORMAT_PCM_16_BIT;
5204 if (config->sample_rate > 48000)
5205 config->sample_rate = 48000;
5206 ret_error = true;
5207 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5208 in->config.format = PCM_FORMAT_S24_3LE;
5209 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5210 in->config.format = PCM_FORMAT_S24_LE;
5211 } else {
5212 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5213 ret_error = true;
5214 }
5215
5216 if (ret_error) {
5217 ret = -EINVAL;
5218 goto err_open;
5219 }
5220 }
5221
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305222 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305223 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5224 (adev->mode != AUDIO_MODE_IN_CALL)) {
5225 ret = -EINVAL;
5226 goto err_open;
5227 }
5228
5229 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5230 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005231 if (config->sample_rate == 0)
5232 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5233 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5234 config->sample_rate != 8000) {
5235 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5236 ret = -EINVAL;
5237 goto err_open;
5238 }
5239 if (config->format == AUDIO_FORMAT_DEFAULT)
5240 config->format = AUDIO_FORMAT_PCM_16_BIT;
5241 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5242 config->format = AUDIO_FORMAT_PCM_16_BIT;
5243 ret = -EINVAL;
5244 goto err_open;
5245 }
5246
5247 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5248 in->config = pcm_config_afe_proxy_record;
5249 in->config.channels = channel_count;
5250 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305251 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305252 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5253 in, config, &channel_mask_updated)) {
5254 if (channel_mask_updated == true) {
5255 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5256 __func__, config->channel_mask);
5257 ret = -EINVAL;
5258 goto err_open;
5259 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305260 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005261 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005262 audio_extn_compr_cap_format_supported(config->format) &&
5263 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005264 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305265 } else if (audio_extn_cin_applicable_stream(in)) {
5266 ret = audio_extn_cin_configure_input_stream(in);
5267 if (ret)
5268 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005269 } else {
5270 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005271 if (!in->realtime) {
5272 in->format = config->format;
5273 frame_size = audio_stream_in_frame_size(&in->stream);
5274 buffer_size = get_input_buffer_size(config->sample_rate,
5275 config->format,
5276 channel_count,
5277 is_low_latency);
5278 in->config.period_size = buffer_size / frame_size;
5279 }
5280
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005281 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005282 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005283 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005284 (in->config.rate == 8000 || in->config.rate == 16000 ||
5285 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005286 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5287 voice_extn_compress_voip_open_input_stream(in);
5288 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005289 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305291 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5292 &adev->streams_input_cfg_list,
5293 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305294 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305295
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005296 /* This stream could be for sound trigger lab,
5297 get sound trigger pcm if present */
5298 audio_extn_sound_trigger_check_and_get_session(in);
5299
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305300 lock_input_stream(in);
5301 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5302 pthread_mutex_lock(&adev->lock);
5303 in->card_status = adev->card_status;
5304 pthread_mutex_unlock(&adev->lock);
5305 pthread_mutex_unlock(&in->lock);
5306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005307 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005308 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005309 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005310
5311err_open:
5312 free(in);
5313 *stream_in = NULL;
5314 return ret;
5315}
5316
5317static void adev_close_input_stream(struct audio_hw_device *dev,
5318 struct audio_stream_in *stream)
5319{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005320 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005321 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005322 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305323
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305324 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005325
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305326 // must deregister from sndmonitor first to prevent races
5327 // between the callback and close_stream
5328 audio_extn_snd_mon_unregister_listener(stream);
5329
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305330 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005331 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305332
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005333 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305334 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005335 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305336 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005337 if (ret != 0)
5338 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5339 __func__, ret);
5340 } else
5341 in_standby(&stream->common);
5342
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005343 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005344 audio_extn_ssr_deinit();
5345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305347 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005348 audio_extn_compr_cap_format_supported(in->config.format))
5349 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305350
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305351 if (audio_extn_cin_attached_usecase(in->usecase))
5352 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005353
Mingming Yinfd7607b2016-01-22 12:48:44 -08005354 if (in->is_st_session) {
5355 ALOGV("%s: sound trigger pcm stop lab", __func__);
5356 audio_extn_sound_trigger_stop_lab(in);
5357 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005358 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005359 return;
5360}
5361
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005362static int adev_dump(const audio_hw_device_t *device __unused,
5363 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364{
5365 return 0;
5366}
5367
5368static int adev_close(hw_device_t *device)
5369{
5370 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005371
5372 if (!adev)
5373 return 0;
5374
5375 pthread_mutex_lock(&adev_init_lock);
5376
5377 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305378 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005379 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005380 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305381 audio_extn_utils_release_streams_cfg_lists(
5382 &adev->streams_output_cfg_list,
5383 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305384 if (audio_extn_qaf_is_enabled())
5385 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005386 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005387 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005388 free(adev->snd_dev_ref_cnt);
5389 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005390 if (adev->adm_deinit)
5391 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305392 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005393 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305394 audio_extn_snd_mon_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005395 free(device);
5396 adev = NULL;
5397 }
5398 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400 return 0;
5401}
5402
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005403/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5404 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5405 * just that it _might_ work.
5406 */
5407static int period_size_is_plausible_for_low_latency(int period_size)
5408{
5409 switch (period_size) {
5410 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005411 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005412 case 240:
5413 case 320:
5414 case 480:
5415 return 1;
5416 default:
5417 return 0;
5418 }
5419}
5420
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305421static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5422{
5423 bool is_snd_card_status = false;
5424 bool is_ext_device_status = false;
5425 char value[32];
5426 int card = -1;
5427 card_status_t status;
5428
5429 if (cookie != adev || !parms)
5430 return;
5431
5432 if (!parse_snd_card_status(parms, &card, &status)) {
5433 is_snd_card_status = true;
5434 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5435 is_ext_device_status = true;
5436 } else {
5437 // not a valid event
5438 return;
5439 }
5440
5441 pthread_mutex_lock(&adev->lock);
5442 if (card == adev->snd_card || is_ext_device_status) {
5443 if (is_snd_card_status && adev->card_status != status) {
5444 adev->card_status = status;
5445 platform_snd_card_update(adev->platform, status);
5446 audio_extn_fm_set_parameters(adev, parms);
5447 } else if (is_ext_device_status) {
5448 platform_set_parameters(adev->platform, parms);
5449 }
5450 }
5451 pthread_mutex_unlock(&adev->lock);
5452 return;
5453}
5454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455static int adev_open(const hw_module_t *module, const char *name,
5456 hw_device_t **device)
5457{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305458 int ret;
5459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005460 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005461 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5462
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005463 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005464 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005465 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005466 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005467 ALOGD("%s: returning existing instance of adev", __func__);
5468 ALOGD("%s: exit", __func__);
5469 pthread_mutex_unlock(&adev_init_lock);
5470 return 0;
5471 }
5472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 adev = calloc(1, sizeof(struct audio_device));
5474
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005475 if (!adev) {
5476 pthread_mutex_unlock(&adev_init_lock);
5477 return -ENOMEM;
5478 }
5479
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005480 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5481
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305482#ifdef DYNAMIC_LOG_ENABLED
5483 register_for_dynamic_logging("hal");
5484#endif
5485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5487 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5488 adev->device.common.module = (struct hw_module_t *)module;
5489 adev->device.common.close = adev_close;
5490
5491 adev->device.init_check = adev_init_check;
5492 adev->device.set_voice_volume = adev_set_voice_volume;
5493 adev->device.set_master_volume = adev_set_master_volume;
5494 adev->device.get_master_volume = adev_get_master_volume;
5495 adev->device.set_master_mute = adev_set_master_mute;
5496 adev->device.get_master_mute = adev_get_master_mute;
5497 adev->device.set_mode = adev_set_mode;
5498 adev->device.set_mic_mute = adev_set_mic_mute;
5499 adev->device.get_mic_mute = adev_get_mic_mute;
5500 adev->device.set_parameters = adev_set_parameters;
5501 adev->device.get_parameters = adev_get_parameters;
5502 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5503 adev->device.open_output_stream = adev_open_output_stream;
5504 adev->device.close_output_stream = adev_close_output_stream;
5505 adev->device.open_input_stream = adev_open_input_stream;
5506 adev->device.close_input_stream = adev_close_input_stream;
5507 adev->device.dump = adev_dump;
5508
5509 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005510 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005511 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005512 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005515 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005516 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305517 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005518 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005519 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005520 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005521 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005522 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005523 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305524 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305525 adev->perf_lock_opts[0] = 0x101;
5526 adev->perf_lock_opts[1] = 0x20E;
5527 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005530 adev->platform = platform_init(adev);
5531 if (!adev->platform) {
5532 free(adev->snd_dev_ref_cnt);
5533 free(adev);
5534 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5535 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005536 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305537 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005538 return -EINVAL;
5539 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005540
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305541 if (audio_extn_qaf_is_enabled()) {
5542 ret = audio_extn_qaf_init(adev);
5543 if (ret < 0) {
5544 free(adev);
5545 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5546 *device = NULL;
5547 pthread_mutex_unlock(&adev_init_lock);
5548 pthread_mutex_destroy(&adev->lock);
5549 return ret;
5550 }
5551
5552 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5553 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5554 }
5555
Eric Laurentc4aef752013-09-12 17:45:53 -07005556 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5557 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5558 if (adev->visualizer_lib == NULL) {
5559 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5560 } else {
5561 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5562 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005563 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005564 "visualizer_hal_start_output");
5565 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005566 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005567 "visualizer_hal_stop_output");
5568 }
5569 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305570 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005571 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005572 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005573
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005574 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5575 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5576 if (adev->offload_effects_lib == NULL) {
5577 ALOGE("%s: DLOPEN failed for %s", __func__,
5578 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5579 } else {
5580 ALOGV("%s: DLOPEN successful for %s", __func__,
5581 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5582 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305583 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005584 "offload_effects_bundle_hal_start_output");
5585 adev->offload_effects_stop_output =
5586 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5587 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005588 adev->offload_effects_set_hpx_state =
5589 (int (*)(bool))dlsym(adev->offload_effects_lib,
5590 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305591 adev->offload_effects_get_parameters =
5592 (void (*)(struct str_parms *, struct str_parms *))
5593 dlsym(adev->offload_effects_lib,
5594 "offload_effects_bundle_get_parameters");
5595 adev->offload_effects_set_parameters =
5596 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5597 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005598 }
5599 }
5600
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005601 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5602 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5603 if (adev->adm_lib == NULL) {
5604 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5605 } else {
5606 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5607 adev->adm_init = (adm_init_t)
5608 dlsym(adev->adm_lib, "adm_init");
5609 adev->adm_deinit = (adm_deinit_t)
5610 dlsym(adev->adm_lib, "adm_deinit");
5611 adev->adm_register_input_stream = (adm_register_input_stream_t)
5612 dlsym(adev->adm_lib, "adm_register_input_stream");
5613 adev->adm_register_output_stream = (adm_register_output_stream_t)
5614 dlsym(adev->adm_lib, "adm_register_output_stream");
5615 adev->adm_deregister_stream = (adm_deregister_stream_t)
5616 dlsym(adev->adm_lib, "adm_deregister_stream");
5617 adev->adm_request_focus = (adm_request_focus_t)
5618 dlsym(adev->adm_lib, "adm_request_focus");
5619 adev->adm_abandon_focus = (adm_abandon_focus_t)
5620 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005621 adev->adm_set_config = (adm_set_config_t)
5622 dlsym(adev->adm_lib, "adm_set_config");
5623 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5624 dlsym(adev->adm_lib, "adm_request_focus_v2");
5625 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5626 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5627 adev->adm_on_routing_change = (adm_on_routing_change_t)
5628 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005629 }
5630 }
5631
Mingming Yin514a8bc2014-07-29 15:22:21 -07005632 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005633 //initialize this to false for now,
5634 //this will be set to true through set param
5635 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005636
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005637 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 *device = &adev->device.common;
5639
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305640 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5641 &adev->streams_output_cfg_list,
5642 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005643
Kiran Kandi910e1862013-10-29 13:29:42 -07005644 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005645
5646 char value[PROPERTY_VALUE_MAX];
5647 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005648 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005649 trial = atoi(value);
5650 if (period_size_is_plausible_for_low_latency(trial)) {
5651 pcm_config_low_latency.period_size = trial;
5652 pcm_config_low_latency.start_threshold = trial / 4;
5653 pcm_config_low_latency.avail_min = trial / 4;
5654 configured_low_latency_capture_period_size = trial;
5655 }
5656 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005657 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005658 trial = atoi(value);
5659 if (period_size_is_plausible_for_low_latency(trial)) {
5660 configured_low_latency_capture_period_size = trial;
5661 }
5662 }
5663
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005664 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005665 af_period_multiplier = atoi(value);
5666 if (af_period_multiplier < 0)
5667 af_period_multiplier = 2;
5668 else if (af_period_multiplier > 4)
5669 af_period_multiplier = 4;
5670
5671 ALOGV("new period_multiplier = %d", af_period_multiplier);
5672 }
5673
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005674 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005675 pthread_mutex_unlock(&adev_init_lock);
5676
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005677 if (adev->adm_init)
5678 adev->adm_data = adev->adm_init();
5679
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305680 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305681 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005682 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305683
5684 audio_extn_snd_mon_init();
5685 pthread_mutex_lock(&adev->lock);
5686 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5687 adev->card_status = CARD_STATUS_ONLINE;
5688 pthread_mutex_unlock(&adev->lock);
5689 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
5690
Eric Laurent994a6932013-07-17 11:51:42 -07005691 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005692 return 0;
5693}
5694
5695static struct hw_module_methods_t hal_module_methods = {
5696 .open = adev_open,
5697};
5698
5699struct audio_module HAL_MODULE_INFO_SYM = {
5700 .common = {
5701 .tag = HARDWARE_MODULE_TAG,
5702 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5703 .hal_api_version = HARDWARE_HAL_API_VERSION,
5704 .id = AUDIO_HARDWARE_MODULE_ID,
5705 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005706 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707 .methods = &hal_module_methods,
5708 },
5709};