blob: 98944460c5252db2ca1a45744303611cf0b8ddb8 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
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
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700258};
259
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700260static const audio_usecase_t offload_usecases[] = {
261 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700262 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
263 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800271
272#define STRING_TO_ENUM(string) { #string, string }
273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800274struct string_to_enum {
275 const char *name;
276 uint32_t value;
277};
278
279static const struct string_to_enum out_channels_name_to_enum_table[] = {
280 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
288};
289
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700290static const struct string_to_enum out_formats_name_to_enum_table[] = {
291 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
292 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800294 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
295 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
296};
297
298//list of all supported sample rates by HDMI specification.
299static const int out_hdmi_sample_rates[] = {
300 32000, 44100, 48000, 88200, 96000, 176400, 192000,
301};
302
303static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
304 STRING_TO_ENUM(32000),
305 STRING_TO_ENUM(44100),
306 STRING_TO_ENUM(48000),
307 STRING_TO_ENUM(88200),
308 STRING_TO_ENUM(96000),
309 STRING_TO_ENUM(176400),
310 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700311};
312
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700313static struct audio_device *adev = NULL;
314static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700315static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700316//cache last MBDRC cal step level
317static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700318
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700319static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
320 int flags __unused)
321{
322 int dir = 0;
323 switch (uc_id) {
324 case USECASE_AUDIO_RECORD_LOW_LATENCY:
325 dir = 1;
326 case USECASE_AUDIO_PLAYBACK_ULL:
327 break;
328 default:
329 return false;
330 }
331
332 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
333 PCM_PLAYBACK : PCM_CAPTURE);
334 if (adev->adm_is_noirq_avail)
335 return adev->adm_is_noirq_avail(adev->adm_data,
336 adev->snd_card, dev_id, dir);
337 return false;
338}
339
340static void register_out_stream(struct stream_out *out)
341{
342 struct audio_device *adev = out->dev;
343 if (is_offload_usecase(out->usecase) ||
344 !adev->adm_register_output_stream)
345 return;
346
347 // register stream first for backward compatibility
348 adev->adm_register_output_stream(adev->adm_data,
349 out->handle,
350 out->flags);
351
352 if (!adev->adm_set_config)
353 return;
354
355 if (out->realtime)
356 adev->adm_set_config(adev->adm_data,
357 out->handle,
358 out->pcm, &out->config);
359}
360
361static void register_in_stream(struct stream_in *in)
362{
363 struct audio_device *adev = in->dev;
364 if (!adev->adm_register_input_stream)
365 return;
366
367 adev->adm_register_input_stream(adev->adm_data,
368 in->capture_handle,
369 in->flags);
370
371 if (!adev->adm_set_config)
372 return;
373
374 if (in->realtime)
375 adev->adm_set_config(adev->adm_data,
376 in->capture_handle,
377 in->pcm,
378 &in->config);
379}
380
381static void request_out_focus(struct stream_out *out, long ns)
382{
383 struct audio_device *adev = out->dev;
384
385 if (out->routing_change) {
386 out->routing_change = false;
387 // must be checked for backward compatibility
388 if (adev->adm_on_routing_change)
389 adev->adm_on_routing_change(adev->adm_data, out->handle);
390 }
391
392 if (adev->adm_request_focus_v2)
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 else if (adev->adm_request_focus)
395 adev->adm_request_focus(adev->adm_data, out->handle);
396}
397
398static void request_in_focus(struct stream_in *in, long ns)
399{
400 struct audio_device *adev = in->dev;
401
402 if (in->routing_change) {
403 in->routing_change = false;
404 if (adev->adm_on_routing_change)
405 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
406 }
407
408 if (adev->adm_request_focus_v2)
409 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
410 else if (adev->adm_request_focus)
411 adev->adm_request_focus(adev->adm_data, in->capture_handle);
412}
413
414static void release_out_focus(struct stream_out *out)
415{
416 struct audio_device *adev = out->dev;
417
418 if (adev->adm_abandon_focus)
419 adev->adm_abandon_focus(adev->adm_data, out->handle);
420}
421
422static void release_in_focus(struct stream_in *in)
423{
424 struct audio_device *adev = in->dev;
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
427}
428
vivek mehtaa76401a2015-04-24 14:12:15 -0700429__attribute__ ((visibility ("default")))
430bool audio_hw_send_gain_dep_calibration(int level) {
431 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700432 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700433
434 pthread_mutex_lock(&adev_init_lock);
435
436 if (adev != NULL && adev->platform != NULL) {
437 pthread_mutex_lock(&adev->lock);
438 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700439
440 // if cal set fails, cache level info
441 // if cal set succeds, reset known last cal set
442 if (!ret_val)
443 last_known_cal_step = level;
444 else if (last_known_cal_step != -1)
445 last_known_cal_step = -1;
446
vivek mehtaa76401a2015-04-24 14:12:15 -0700447 pthread_mutex_unlock(&adev->lock);
448 } else {
449 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
450 }
451
452 pthread_mutex_unlock(&adev_init_lock);
453
454 return ret_val;
455}
456
Ashish Jain5106d362016-05-11 19:23:33 +0530457static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
458{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459 bool gapless_enabled = false;
460 const char *mixer_ctl_name = "Compress Gapless Playback";
461 struct mixer_ctl *ctl;
462
463 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530464 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
465
466 /*Disable gapless if its AV playback*/
467 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800468
469 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
470 if (!ctl) {
471 ALOGE("%s: Could not get ctl for mixer cmd - %s",
472 __func__, mixer_ctl_name);
473 return -EINVAL;
474 }
475
476 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
477 ALOGE("%s: Could not set gapless mode %d",
478 __func__, gapless_enabled);
479 return -EINVAL;
480 }
481 return 0;
482}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700483
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700484static bool is_supported_format(audio_format_t format)
485{
Eric Laurent86e17132013-09-12 17:49:30 -0700486 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530487 format == AUDIO_FORMAT_AAC_LC ||
488 format == AUDIO_FORMAT_AAC_HE_V1 ||
489 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530490 format == AUDIO_FORMAT_AAC_ADTS_LC ||
491 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530493 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
494 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530495 format == AUDIO_FORMAT_PCM_FLOAT ||
496 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700497 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530498 format == AUDIO_FORMAT_AC3 ||
499 format == AUDIO_FORMAT_E_AC3 ||
500 format == AUDIO_FORMAT_DTS ||
501 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800502 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530503 format == AUDIO_FORMAT_ALAC ||
504 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530505 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530506 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800507 format == AUDIO_FORMAT_WMA ||
508 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800509 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700510
511 return false;
512}
513
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700514static inline bool is_mmap_usecase(audio_usecase_t uc_id)
515{
516 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
517 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
518}
519
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520static int get_snd_codec_id(audio_format_t format)
521{
522 int id = 0;
523
Ashish Jainf9b78162014-08-25 20:36:25 +0530524 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525 case AUDIO_FORMAT_MP3:
526 id = SND_AUDIOCODEC_MP3;
527 break;
528 case AUDIO_FORMAT_AAC:
529 id = SND_AUDIOCODEC_AAC;
530 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530531 case AUDIO_FORMAT_AAC_ADTS:
532 id = SND_AUDIOCODEC_AAC;
533 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700534 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800535 id = SND_AUDIOCODEC_PCM;
536 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700537 case AUDIO_FORMAT_FLAC:
538 id = SND_AUDIOCODEC_FLAC;
539 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530540 case AUDIO_FORMAT_ALAC:
541 id = SND_AUDIOCODEC_ALAC;
542 break;
543 case AUDIO_FORMAT_APE:
544 id = SND_AUDIOCODEC_APE;
545 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530546 case AUDIO_FORMAT_DSD:
547 id = SND_AUDIOCODEC_DSD;
548 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530549 case AUDIO_FORMAT_VORBIS:
550 id = SND_AUDIOCODEC_VORBIS;
551 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800552 case AUDIO_FORMAT_WMA:
553 id = SND_AUDIOCODEC_WMA;
554 break;
555 case AUDIO_FORMAT_WMA_PRO:
556 id = SND_AUDIOCODEC_WMA_PRO;
557 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530558 case AUDIO_FORMAT_AC3:
559 id = SND_AUDIOCODEC_AC3;
560 break;
561 case AUDIO_FORMAT_E_AC3:
562 case AUDIO_FORMAT_E_AC3_JOC:
563 id = SND_AUDIOCODEC_EAC3;
564 break;
565 case AUDIO_FORMAT_DTS:
566 case AUDIO_FORMAT_DTS_HD:
567 id = SND_AUDIOCODEC_DTS;
568 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700569 default:
Mingming Yin90310102013-11-13 16:57:00 -0800570 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700571 }
572
573 return id;
574}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800575
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530576int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530577{
578 int snd_scard_state;
579
580 if (!adev)
581 return SND_CARD_STATE_OFFLINE;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
584 snd_scard_state = adev->snd_card_status.state;
585 pthread_mutex_unlock(&adev->snd_card_status.lock);
586
587 return snd_scard_state;
588}
589
590static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
591{
592 if (!adev)
593 return -ENOSYS;
594
595 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700596 if (adev->snd_card_status.state != snd_scard_state) {
597 adev->snd_card_status.state = snd_scard_state;
598 platform_snd_card_update(adev->platform, snd_scard_state);
599 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530600 pthread_mutex_unlock(&adev->snd_card_status.lock);
601
602 return 0;
603}
604
Avinash Vaish71a8b972014-07-24 15:36:33 +0530605static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
606 struct audio_usecase *uc_info)
607{
608 struct listnode *node;
609 struct audio_usecase *usecase;
610
611 if (uc_info == NULL)
612 return -EINVAL;
613
614 /* Re-route all voice usecases on the shared backend other than the
615 specified usecase to new snd devices */
616 list_for_each(node, &adev->usecase_list) {
617 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800618 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530619 enable_audio_route(adev, usecase);
620 }
621 return 0;
622}
623
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530624/*
625 * Enable ASRC mode if native or DSD stream is active.
626 */
627static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
628{
629 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
630 !adev->asrc_mode_enabled) {
631 struct listnode *node = NULL;
632 struct audio_usecase *uc = NULL;
633 struct stream_out *curr_out = NULL;
634
635 list_for_each(node, &adev->usecase_list) {
636 uc = node_to_item(node, struct audio_usecase, list);
637 curr_out = (struct stream_out*) uc->stream.out;
638
639 if (curr_out && PCM_PLAYBACK == uc->type) {
640 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
641 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
642 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
643 __func__);
644 audio_route_apply_and_update_path(adev->audio_route,
645 "asrc-mode");
646 adev->asrc_mode_enabled = true;
647 break;
648 }
649 }
650 }
651 }
652}
653
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700654int pcm_ioctl(struct pcm *pcm, int request, ...)
655{
656 va_list ap;
657 void * arg;
658 int pcm_fd = *(int*)pcm;
659
660 va_start(ap, request);
661 arg = va_arg(ap, void *);
662 va_end(ap);
663
664 return ioctl(pcm_fd, request, arg);
665}
666
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700667int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700668 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700671 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800672
673 if (usecase == NULL)
674 return -EINVAL;
675
676 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
677
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800678 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800682
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800683#ifdef DS1_DOLBY_DAP_ENABLED
684 audio_extn_dolby_set_dmid(adev);
685 audio_extn_dolby_set_endpoint(adev);
686#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700687 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700688 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530689 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700690 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530691 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800692 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700693 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700694 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800696 ALOGV("%s: exit", __func__);
697 return 0;
698}
699
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700700int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700701 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700704 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800705
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530706 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800707 return -EINVAL;
708
709 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (usecase->type == PCM_CAPTURE)
711 snd_device = usecase->in_snd_device;
712 else
713 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800714 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700715 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700716 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700717 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700718 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530719 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720 ALOGV("%s: exit", __func__);
721 return 0;
722}
723
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700724int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700729 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
730
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800731 if (snd_device < SND_DEVICE_MIN ||
732 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800733 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800734 return -EINVAL;
735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736
737 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700738
739 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
740 ALOGE("%s: Invalid sound device returned", __func__);
741 return -EINVAL;
742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700743 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700744 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700745 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 return 0;
747 }
748
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530749
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700750 if (audio_extn_spkr_prot_is_enabled())
751 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700752
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530754 if (((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
755 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
756 && (audio_extn_a2dp_start_playback() < 0)) {
757 ALOGE(" fail to configure A2dp control path ");
758 return -EINVAL;
759 }
760
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800761 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
762 audio_extn_spkr_prot_is_enabled()) {
763 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700764 adev->snd_dev_ref_cnt[snd_device]--;
765 return -EINVAL;
766 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200767 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800768 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800769 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200770 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 return -EINVAL;
772 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530773 } else if (platform_can_split_snd_device(adev->platform, snd_device,
774 &num_devices, new_snd_devices)) {
775 for (i = 0; i < num_devices; i++) {
776 enable_snd_device(adev, new_snd_devices[i]);
777 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800778 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700779 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700780 /* due to the possibility of calibration overwrite between listen
781 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700782 audio_extn_sound_trigger_update_device_status(snd_device,
783 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530784 audio_extn_listen_update_device_status(snd_device,
785 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700786 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 audio_extn_sound_trigger_update_device_status(snd_device,
789 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530790 audio_extn_listen_update_device_status(snd_device,
791 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700792 return -EINVAL;
793 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300794 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
797 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
798 !adev->native_playback_enabled &&
799 audio_is_true_native_stream_active(adev)) {
800 ALOGD("%s: %d: napb: enabling native mode in hardware",
801 __func__, __LINE__);
802 audio_route_apply_and_update_path(adev->audio_route,
803 "true-native-mode");
804 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530805 } else
806 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530814 int i, num_devices = 0;
815 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 if (snd_device < SND_DEVICE_MIN ||
819 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 return -EINVAL;
822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
824 ALOGE("%s: device ref cnt is already 0", __func__);
825 return -EINVAL;
826 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700829
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
831 ALOGE("%s: Invalid sound device returned", __func__);
832 return -EINVAL;
833 }
834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700836 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530837
838 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
839 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
840 audio_extn_a2dp_stop_playback();
841
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800842 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
843 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700844 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530845 } else if (platform_can_split_snd_device(adev->platform, snd_device,
846 &num_devices, new_snd_devices)) {
847 for (i = 0; i < num_devices; i++) {
848 disable_snd_device(adev, new_snd_devices[i]);
849 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300850 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700851 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 if (snd_device == SND_DEVICE_OUT_HDMI)
855 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530856 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
857 adev->native_playback_enabled) {
858 ALOGD("%s: %d: napb: disabling native mode in hardware",
859 __func__, __LINE__);
860 audio_route_reset_and_update_path(adev->audio_route,
861 "true-native-mode");
862 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530863 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
864 adev->asrc_mode_enabled) {
865 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
866 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
867 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530868 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530869
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200870 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700871 audio_extn_sound_trigger_update_device_status(snd_device,
872 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530873 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800874 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 return 0;
878}
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530881 struct audio_usecase *uc_info,
882 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883{
884 struct listnode *node;
885 struct audio_usecase *usecase;
886 bool switch_device[AUDIO_USECASE_MAX];
887 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530888 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 /*
890 * This function is to make sure that all the usecases that are active on
891 * the hardware codec backend are always routed to any one device that is
892 * handled by the hardware codec.
893 * For example, if low-latency and deep-buffer usecases are currently active
894 * on speaker and out_set_parameters(headset) is received on low-latency
895 * output, then we have to make sure deep-buffer is also switched to headset,
896 * because of the limitation that both the devices cannot be enabled
897 * at the same time as they share the same backend.
898 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700899 /*
900 * This call is to check if we need to force routing for a particular stream
901 * If there is a backend configuration change for the device when a
902 * new stream starts, then ADM needs to be closed and re-opened with the new
903 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800904 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700905 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800906 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
907 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530908 /* For a2dp device reconfigure all active sessions
909 * with new AFE encoder format based on a2dp state
910 */
911 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 force_restart_session = true;
916 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530917 ALOGD("%s:becf: force routing %d", __func__, force_routing);
918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800921 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 for (i = 0; i < AUDIO_USECASE_MAX; i++)
923 switch_device[i] = false;
924
925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800927
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530928 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
929 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530930 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530931 platform_get_snd_device_name(usecase->out_snd_device),
932 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800933 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530934 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530935 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530936 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
937 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
938 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530939 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
940 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
941 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530942 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
944 platform_get_snd_device_name(usecase->out_snd_device));
945 disable_audio_route(adev, usecase);
946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530951 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
952 num_uc_to_switch);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700955 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530957 /* Make sure the previous devices to be disabled first and then enable the
958 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 }
964 }
965
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700970 }
971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 /* Re-route all the usecases on the shared backend other than the
974 specified usecase to new snd devices */
975 list_for_each(node, &adev->usecase_list) {
976 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530977 /* Update the out_snd_device only before enabling the audio route */
978 if (switch_device[usecase->id]) {
979 usecase->out_snd_device = snd_device;
980 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530981 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530982 use_case_table[usecase->id],
983 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989}
990
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530991static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 struct audio_usecase *uc_info,
993 snd_device_t snd_device)
994{
995 struct listnode *node;
996 struct audio_usecase *usecase;
997 bool switch_device[AUDIO_USECASE_MAX];
998 int i, num_uc_to_switch = 0;
999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301000 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1001 snd_device);
1002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001018 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301020 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001021 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301022 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001023 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001024 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001025 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1026 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001027 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001029 switch_device[usecase->id] = true;
1030 num_uc_to_switch++;
1031 }
1032 }
1033
1034 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001035 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301037 /* Make sure the previous devices to be disabled first and then enable the
1038 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001043 }
1044 }
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001049 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 }
1051 }
1052
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001053 /* Re-route all the usecases on the shared backend other than the
1054 specified usecase to new snd devices */
1055 list_for_each(node, &adev->usecase_list) {
1056 usecase = node_to_item(node, struct audio_usecase, list);
1057 /* Update the in_snd_device only before enabling the audio route */
1058 if (switch_device[usecase->id] ) {
1059 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001060 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301061 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001064 }
1065}
1066
Mingming Yin3a941d42016-02-17 18:08:05 -08001067static void reset_hdmi_sink_caps(struct stream_out *out) {
1068 int i = 0;
1069
1070 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1071 out->supported_channel_masks[i] = 0;
1072 }
1073 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1074 out->supported_formats[i] = 0;
1075 }
1076 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1077 out->supported_sample_rates[i] = 0;
1078 }
1079}
1080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001082static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083{
Mingming Yin3a941d42016-02-17 18:08:05 -08001084 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001085 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Mingming Yin3a941d42016-02-17 18:08:05 -08001087 reset_hdmi_sink_caps(out);
1088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001091 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001092 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001093 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1094 case 6:
1095 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1096 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1097 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1098 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 break;
1102 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001103 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001104 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 break;
1106 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001107
1108 // check channel format caps
1109 i = 0;
1110 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1111 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1112 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1113 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1114 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1115 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1116 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1117 }
1118
1119 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1120 ALOGV(":%s HDMI supports DTS format", __func__);
1121 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1122 }
1123
1124 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1125 ALOGV(":%s HDMI supports DTS HD format", __func__);
1126 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1127 }
1128
1129
1130 // check sample rate caps
1131 i = 0;
1132 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1133 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1134 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1135 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1136 }
1137 }
1138
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001139 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140}
1141
Alexy Josephb1379942016-01-29 15:49:38 -08001142audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001143 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001144{
1145 struct audio_usecase *usecase;
1146 struct listnode *node;
1147
1148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151 ALOGV("%s: usecase id %d", __func__, usecase->id);
1152 return usecase->id;
1153 }
1154 }
1155 return USECASE_INVALID;
1156}
1157
Alexy Josephb1379942016-01-29 15:49:38 -08001158struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001159 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160{
1161 struct audio_usecase *usecase;
1162 struct listnode *node;
1163
1164 list_for_each(node, &adev->usecase_list) {
1165 usecase = node_to_item(node, struct audio_usecase, list);
1166 if (usecase->id == uc_id)
1167 return usecase;
1168 }
1169 return NULL;
1170}
1171
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301172/*
1173 * is a true native playback active
1174 */
1175bool audio_is_true_native_stream_active(struct audio_device *adev)
1176{
1177 bool active = false;
1178 int i = 0;
1179 struct listnode *node;
1180
1181 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1182 ALOGV("%s:napb: not in true mode or non hdphones device",
1183 __func__);
1184 active = false;
1185 goto exit;
1186 }
1187
1188 list_for_each(node, &adev->usecase_list) {
1189 struct audio_usecase *uc;
1190 uc = node_to_item(node, struct audio_usecase, list);
1191 struct stream_out *curr_out =
1192 (struct stream_out*) uc->stream.out;
1193
1194 if (curr_out && PCM_PLAYBACK == uc->type) {
1195 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1196 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1197 uc->id, curr_out->sample_rate,
1198 curr_out->bit_width,
1199 platform_get_snd_device_name(uc->out_snd_device));
1200
1201 if (is_offload_usecase(uc->id) &&
1202 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1203 active = true;
1204 ALOGD("%s:napb:native stream detected", __func__);
1205 }
1206 }
1207 }
1208exit:
1209 return active;
1210}
1211
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301212/*
1213 * if native DSD playback active
1214 */
1215bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1216{
1217 bool active = false;
1218 struct listnode *node = NULL;
1219 struct audio_usecase *uc = NULL;
1220 struct stream_out *curr_out = NULL;
1221
1222 list_for_each(node, &adev->usecase_list) {
1223 uc = node_to_item(node, struct audio_usecase, list);
1224 curr_out = (struct stream_out*) uc->stream.out;
1225
1226 if (curr_out && PCM_PLAYBACK == uc->type &&
1227 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1228 active = true;
1229 ALOGV("%s:DSD playback is active", __func__);
1230 }
1231 }
1232 return active;
1233}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301234
1235static bool force_device_switch(struct audio_usecase *usecase)
1236{
1237 bool ret = false;
1238 bool is_it_true_mode = false;
1239
1240 if (is_offload_usecase(usecase->id) &&
1241 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001242 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1243 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1244 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301245 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1246 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1247 (!is_it_true_mode && adev->native_playback_enabled)){
1248 ret = true;
1249 ALOGD("napb: time to toggle native mode");
1250 }
1251 }
1252
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301253 // Force all a2dp output devices to reconfigure for proper AFE encode format
1254 if((usecase->stream.out) &&
1255 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1256 audio_extn_a2dp_is_force_device_switch()) {
1257 ALOGD("Force a2dp device switch to update new encoder config");
1258 ret = true;
1259 }
1260
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301261 return ret;
1262}
1263
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001264int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001266 snd_device_t out_snd_device = SND_DEVICE_NONE;
1267 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 struct audio_usecase *usecase = NULL;
1269 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001270 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001271 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001272 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301275 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 usecase = get_usecase_from_list(adev, uc_id);
1278 if (usecase == NULL) {
1279 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1280 return -EINVAL;
1281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001283 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001284 (usecase->type == VOIP_CALL) ||
1285 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001286 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001287 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001288 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 usecase->devices = usecase->stream.out->devices;
1290 } else {
1291 /*
1292 * If the voice call is active, use the sound devices of voice call usecase
1293 * so that it would not result any device switch. All the usecases will
1294 * be switched to new device when select_devices() is called for voice call
1295 * usecase. This is to avoid switching devices for voice call when
1296 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001297 * choose voice call device only if the use case device is
1298 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001300 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001301 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001302 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001303 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1304 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301305 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1306 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001307 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 in_snd_device = vc_usecase->in_snd_device;
1309 out_snd_device = vc_usecase->out_snd_device;
1310 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001311 } else if (voice_extn_compress_voip_is_active(adev)) {
1312 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001313 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001314 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1315 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001316 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001317 in_snd_device = voip_usecase->in_snd_device;
1318 out_snd_device = voip_usecase->out_snd_device;
1319 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001320 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001321 hfp_ucid = audio_extn_hfp_get_usecase();
1322 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001323 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001324 in_snd_device = hfp_usecase->in_snd_device;
1325 out_snd_device = hfp_usecase->out_snd_device;
1326 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 }
1328 if (usecase->type == PCM_PLAYBACK) {
1329 usecase->devices = usecase->stream.out->devices;
1330 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001331 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001332 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001333 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001334 if (usecase->stream.out == adev->primary_output &&
1335 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001336 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001337 select_devices(adev, adev->active_input->usecase);
1338 }
1339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 } else if (usecase->type == PCM_CAPTURE) {
1341 usecase->devices = usecase->stream.in->device;
1342 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001343 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001344 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001345 if (adev->active_input &&
1346 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301347 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1348 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1349 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001350 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001351 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001352 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1353 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001354 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001355 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001356 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 }
1358 }
1359
1360 if (out_snd_device == usecase->out_snd_device &&
1361 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301362
1363 if (!force_device_switch(usecase))
1364 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365 }
1366
sangwoobc677242013-08-08 16:53:43 +09001367 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001368 out_snd_device, platform_get_snd_device_name(out_snd_device),
1369 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371 /*
1372 * Limitation: While in call, to do a device switch we need to disable
1373 * and enable both RX and TX devices though one of them is same as current
1374 * device.
1375 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001376 if ((usecase->type == VOICE_CALL) &&
1377 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1378 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001379 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001380 }
1381
1382 if (((usecase->type == VOICE_CALL) ||
1383 (usecase->type == VOIP_CALL)) &&
1384 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1385 /* Disable sidetone only if voice/voip call already exists */
1386 if (voice_is_call_state_active(adev) ||
1387 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001388 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001389 }
1390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 /* Disable current sound devices */
1392 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001393 disable_audio_route(adev, usecase);
1394 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 }
1396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001398 disable_audio_route(adev, usecase);
1399 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 }
1401
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001402 /* Applicable only on the targets that has external modem.
1403 * New device information should be sent to modem before enabling
1404 * the devices to reduce in-call device switch time.
1405 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001406 if ((usecase->type == VOICE_CALL) &&
1407 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1408 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001409 status = platform_switch_voice_call_enable_device_config(adev->platform,
1410 out_snd_device,
1411 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001412 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 /* Enable new sound devices */
1415 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001416 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001417 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418 }
1419
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001420 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301421 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001423 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424
Avinash Vaish71a8b972014-07-24 15:36:33 +05301425 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001426 status = platform_switch_voice_call_device_post(adev->platform,
1427 out_snd_device,
1428 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301429 enable_audio_route_for_voice_usecases(adev, usecase);
1430 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001431
sangwoo170731f2013-06-08 15:36:36 +09001432 usecase->in_snd_device = in_snd_device;
1433 usecase->out_snd_device = out_snd_device;
1434
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301435 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001436 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301437 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001438 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301439 usecase->stream.out->flags,
1440 usecase->stream.out->format,
1441 usecase->stream.out->sample_rate,
1442 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301443 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301444 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001445 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301446 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001447
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001449
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001450 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1451 /* Enable sidetone only if other voice/voip call already exists */
1452 if (voice_is_call_state_active(adev) ||
1453 voice_extn_compress_voip_is_started(adev))
1454 voice_set_sidetone(adev, out_snd_device, true);
1455 }
1456
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001457 /* Applicable only on the targets that has external modem.
1458 * Enable device command should be sent to modem only after
1459 * enabling voice call mixer controls
1460 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001461 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001462 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1463 out_snd_device,
1464 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301465 ALOGD("%s: done",__func__);
1466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 return status;
1468}
1469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470static int stop_input_stream(struct stream_in *in)
1471{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301472 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 struct audio_usecase *uc_info;
1474 struct audio_device *adev = in->dev;
1475
Eric Laurentc8400632013-02-14 19:04:54 -08001476 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Eric Laurent994a6932013-07-17 11:51:42 -07001478 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 uc_info = get_usecase_from_list(adev, in->usecase);
1481 if (uc_info == NULL) {
1482 ALOGE("%s: Could not find the usecase (%d) in the list",
1483 __func__, in->usecase);
1484 return -EINVAL;
1485 }
1486
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001487 /* Close in-call recording streams */
1488 voice_check_and_stop_incall_rec_usecase(adev, in);
1489
Eric Laurent150dbfe2013-02-27 14:31:02 -08001490 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492
1493 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001494 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001496 list_remove(&uc_info->list);
1497 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498
Eric Laurent994a6932013-07-17 11:51:42 -07001499 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500 return ret;
1501}
1502
1503int start_input_stream(struct stream_in *in)
1504{
1505 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001506 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 struct audio_usecase *uc_info;
1508 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301509 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510
Mingming Yin2664a5b2015-09-03 10:53:11 -07001511 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1512 if (get_usecase_from_list(adev, usecase) == NULL)
1513 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301514 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1515 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001516
Naresh Tanniru80659832014-06-04 18:17:56 +05301517
1518 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301519 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301520 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301521 goto error_config;
1522 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301523
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001524 /* Check if source matches incall recording usecase criteria */
1525 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1526 if (ret)
1527 goto error_config;
1528 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001529 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1530
1531 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1532 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1533 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001534 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001535 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001536
Eric Laurentb23d5282013-05-14 15:27:20 -07001537 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 if (in->pcm_device_id < 0) {
1539 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1540 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001541 ret = -EINVAL;
1542 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544
1545 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001547
1548 if (!uc_info) {
1549 ret = -ENOMEM;
1550 goto error_config;
1551 }
1552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 uc_info->id = in->usecase;
1554 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001555 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 uc_info->devices = in->device;
1557 uc_info->in_snd_device = SND_DEVICE_NONE;
1558 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001560 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301561 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1562 adev->perf_lock_opts,
1563 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301566 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1567 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001568
1569 unsigned int flags = PCM_IN;
1570 unsigned int pcm_open_retry_count = 0;
1571
1572 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1573 flags |= PCM_MMAP | PCM_NOIRQ;
1574 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001575 } else if (in->realtime) {
1576 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001577 }
1578
1579 while (1) {
1580 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1581 flags, &in->config);
1582 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1584 if (in->pcm != NULL) {
1585 pcm_close(in->pcm);
1586 in->pcm = NULL;
1587 }
1588 if (pcm_open_retry_count-- == 0) {
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1593 continue;
1594 }
1595 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001597
1598 ALOGV("%s: pcm_prepare", __func__);
1599 ret = pcm_prepare(in->pcm);
1600 if (ret < 0) {
1601 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1602 pcm_close(in->pcm);
1603 in->pcm = NULL;
1604 goto error_open;
1605 }
1606
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001607 register_in_stream(in);
1608 if (in->realtime) {
1609 ret = pcm_start(in->pcm);
1610 if (ret < 0)
1611 goto error_open;
1612 }
1613
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301614 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001615 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001616
Eric Laurentc8400632013-02-14 19:04:54 -08001617 return ret;
1618
1619error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301620 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001622error_config:
1623 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301624 /*
1625 * sleep 50ms to allow sufficient time for kernel
1626 * drivers to recover incases like SSR.
1627 */
1628 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001630
1631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632}
1633
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001634void lock_input_stream(struct stream_in *in)
1635{
1636 pthread_mutex_lock(&in->pre_lock);
1637 pthread_mutex_lock(&in->lock);
1638 pthread_mutex_unlock(&in->pre_lock);
1639}
1640
1641void lock_output_stream(struct stream_out *out)
1642{
1643 pthread_mutex_lock(&out->pre_lock);
1644 pthread_mutex_lock(&out->lock);
1645 pthread_mutex_unlock(&out->pre_lock);
1646}
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648/* must be called with out->lock locked */
1649static int send_offload_cmd_l(struct stream_out* out, int command)
1650{
1651 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1652
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001653 if (!cmd) {
1654 ALOGE("failed to allocate mem for command 0x%x", command);
1655 return -ENOMEM;
1656 }
1657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 ALOGVV("%s %d", __func__, command);
1659
1660 cmd->cmd = command;
1661 list_add_tail(&out->offload_cmd_list, &cmd->node);
1662 pthread_cond_signal(&out->offload_cond);
1663 return 0;
1664}
1665
1666/* must be called iwth out->lock locked */
1667static void stop_compressed_output_l(struct stream_out *out)
1668{
1669 out->offload_state = OFFLOAD_STATE_IDLE;
1670 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001671 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672 if (out->compr != NULL) {
1673 compress_stop(out->compr);
1674 while (out->offload_thread_blocked) {
1675 pthread_cond_wait(&out->cond, &out->lock);
1676 }
1677 }
1678}
1679
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001680bool is_offload_usecase(audio_usecase_t uc_id)
1681{
1682 unsigned int i;
1683 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1684 if (uc_id == offload_usecases[i])
1685 return true;
1686 }
1687 return false;
1688}
1689
vivek mehta446c3962015-09-14 10:57:35 -07001690static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001691{
vivek mehta446c3962015-09-14 10:57:35 -07001692 audio_usecase_t ret_uc = USECASE_INVALID;
1693 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001694 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001695 if (!adev->multi_offload_enable) {
1696 if (is_direct_pcm)
1697 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1698 else
1699 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001700
vivek mehta446c3962015-09-14 10:57:35 -07001701 pthread_mutex_lock(&adev->lock);
1702 if (get_usecase_from_list(adev, ret_uc) != NULL)
1703 ret_uc = USECASE_INVALID;
1704 pthread_mutex_unlock(&adev->lock);
1705
1706 return ret_uc;
1707 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001708
1709 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001710 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1711 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1712 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1713 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001714 break;
1715 }
1716 }
vivek mehta446c3962015-09-14 10:57:35 -07001717
1718 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1719 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001720}
1721
1722static void free_offload_usecase(struct audio_device *adev,
1723 audio_usecase_t uc_id)
1724{
vivek mehta446c3962015-09-14 10:57:35 -07001725 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001726 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001727
1728 if (!adev->multi_offload_enable)
1729 return;
1730
1731 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1732 if (offload_usecases[offload_uc_index] == uc_id) {
1733 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001734 break;
1735 }
1736 }
1737 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1738}
1739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740static void *offload_thread_loop(void *context)
1741{
1742 struct stream_out *out = (struct stream_out *) context;
1743 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001744 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1747 set_sched_policy(0, SP_FOREGROUND);
1748 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1749
1750 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 for (;;) {
1753 struct offload_cmd *cmd = NULL;
1754 stream_callback_event_t event;
1755 bool send_callback = false;
1756
1757 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1758 __func__, list_empty(&out->offload_cmd_list),
1759 out->offload_state);
1760 if (list_empty(&out->offload_cmd_list)) {
1761 ALOGV("%s SLEEPING", __func__);
1762 pthread_cond_wait(&out->offload_cond, &out->lock);
1763 ALOGV("%s RUNNING", __func__);
1764 continue;
1765 }
1766
1767 item = list_head(&out->offload_cmd_list);
1768 cmd = node_to_item(item, struct offload_cmd, node);
1769 list_remove(item);
1770
1771 ALOGVV("%s STATE %d CMD %d out->compr %p",
1772 __func__, out->offload_state, cmd->cmd, out->compr);
1773
1774 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1775 free(cmd);
1776 break;
1777 }
1778
1779 if (out->compr == NULL) {
1780 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001781 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 pthread_cond_signal(&out->cond);
1783 continue;
1784 }
1785 out->offload_thread_blocked = true;
1786 pthread_mutex_unlock(&out->lock);
1787 send_callback = false;
1788 switch(cmd->cmd) {
1789 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001790 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001792 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 send_callback = true;
1794 event = STREAM_CBK_EVENT_WRITE_READY;
1795 break;
1796 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001797 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301798 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001799 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301800 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001801 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301802 if (ret < 0)
1803 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301804 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301805 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001806 compress_drain(out->compr);
1807 else
1808 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301809 if (ret != -ENETRESET) {
1810 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301811 pthread_mutex_lock(&out->lock);
1812 out->send_new_metadata = 1;
1813 out->send_next_track_params = true;
1814 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301815 event = STREAM_CBK_EVENT_DRAIN_READY;
1816 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1817 } else
1818 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 break;
1820 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001821 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001823 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 send_callback = true;
1825 event = STREAM_CBK_EVENT_DRAIN_READY;
1826 break;
1827 default:
1828 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1829 break;
1830 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001831 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832 out->offload_thread_blocked = false;
1833 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001834 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001835 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001837 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838 free(cmd);
1839 }
1840
1841 pthread_cond_signal(&out->cond);
1842 while (!list_empty(&out->offload_cmd_list)) {
1843 item = list_head(&out->offload_cmd_list);
1844 list_remove(item);
1845 free(node_to_item(item, struct offload_cmd, node));
1846 }
1847 pthread_mutex_unlock(&out->lock);
1848
1849 return NULL;
1850}
1851
1852static int create_offload_callback_thread(struct stream_out *out)
1853{
1854 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1855 list_init(&out->offload_cmd_list);
1856 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1857 offload_thread_loop, out);
1858 return 0;
1859}
1860
1861static int destroy_offload_callback_thread(struct stream_out *out)
1862{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 stop_compressed_output_l(out);
1865 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1866
1867 pthread_mutex_unlock(&out->lock);
1868 pthread_join(out->offload_thread, (void **) NULL);
1869 pthread_cond_destroy(&out->offload_cond);
1870
1871 return 0;
1872}
1873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874static int stop_output_stream(struct stream_out *out)
1875{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301876 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 struct audio_usecase *uc_info;
1878 struct audio_device *adev = out->dev;
1879
Eric Laurent994a6932013-07-17 11:51:42 -07001880 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 uc_info = get_usecase_from_list(adev, out->usecase);
1883 if (uc_info == NULL) {
1884 ALOGE("%s: Could not find the usecase (%d) in the list",
1885 __func__, out->usecase);
1886 return -EINVAL;
1887 }
1888
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001889 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301890 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001891 if (adev->visualizer_stop_output != NULL)
1892 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001893
1894 audio_extn_dts_remove_state_notifier_node(out->usecase);
1895
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001896 if (adev->offload_effects_stop_output != NULL)
1897 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1898 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001899
Eric Laurent150dbfe2013-02-27 14:31:02 -08001900 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001901 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902
1903 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001904 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001906 list_remove(&uc_info->list);
1907 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001909 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301910 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001911 ALOGV("Disable passthrough , reset mixer to pcm");
1912 /* NO_PASSTHROUGH */
1913 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001914 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001915 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1916 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001917
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301918 /* Must be called after removing the usecase from list */
1919 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301920 audio_extn_keep_alive_start();
1921
Eric Laurent994a6932013-07-17 11:51:42 -07001922 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 return ret;
1924}
1925
1926int start_output_stream(struct stream_out *out)
1927{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 struct audio_usecase *uc_info;
1930 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301931 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001933 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1934 ret = -EINVAL;
1935 goto error_config;
1936 }
1937
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301938 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1939 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1940 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301941
Naresh Tanniru80659832014-06-04 18:17:56 +05301942 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301943 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301944 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301945 goto error_config;
1946 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301947
Eric Laurentb23d5282013-05-14 15:27:20 -07001948 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 if (out->pcm_device_id < 0) {
1950 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1951 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001952 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001953 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 }
1955
1956 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001957
1958 if (!uc_info) {
1959 ret = -ENOMEM;
1960 goto error_config;
1961 }
1962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 uc_info->id = out->usecase;
1964 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001965 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 uc_info->devices = out->devices;
1967 uc_info->in_snd_device = SND_DEVICE_NONE;
1968 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001969 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301971 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1972 adev->perf_lock_opts,
1973 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301974
1975 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1976 audio_extn_keep_alive_stop();
1977 if (audio_extn_passthru_is_enabled() &&
1978 audio_extn_passthru_is_passthrough_stream(out)) {
1979 audio_extn_passthru_on_start(out);
1980 audio_extn_passthru_update_stream_configuration(adev, out);
1981 }
1982 }
1983
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 select_devices(adev, out->usecase);
1985
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001986 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1987 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001988 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001989 unsigned int flags = PCM_OUT;
1990 unsigned int pcm_open_retry_count = 0;
1991 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1992 flags |= PCM_MMAP | PCM_NOIRQ;
1993 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001994 } else if (out->realtime) {
1995 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001996 } else
1997 flags |= PCM_MONOTONIC;
1998
1999 while (1) {
2000 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2001 flags, &out->config);
2002 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2003 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2004 if (out->pcm != NULL) {
2005 pcm_close(out->pcm);
2006 out->pcm = NULL;
2007 }
2008 if (pcm_open_retry_count-- == 0) {
2009 ret = -EIO;
2010 goto error_open;
2011 }
2012 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2013 continue;
2014 }
2015 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002017
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002018 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2019 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002020
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002021 ALOGV("%s: pcm_prepare", __func__);
2022 if (pcm_is_ready(out->pcm)) {
2023 ret = pcm_prepare(out->pcm);
2024 if (ret < 0) {
2025 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2026 pcm_close(out->pcm);
2027 out->pcm = NULL;
2028 goto error_open;
2029 }
2030 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2033 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002035 out->compr = compress_open(adev->snd_card,
2036 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 COMPRESS_IN, &out->compr_config);
2038 if (out->compr && !is_compress_ready(out->compr)) {
2039 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2040 compress_close(out->compr);
2041 out->compr = NULL;
2042 ret = -EIO;
2043 goto error_open;
2044 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302045 /* compress_open sends params of the track, so reset the flag here */
2046 out->is_compr_metadata_avail = false;
2047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 if (out->offload_callback)
2049 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002050
Fred Oh3f43e742015-03-04 18:42:34 -08002051 /* Since small bufs uses blocking writes, a write will be blocked
2052 for the default max poll time (20s) in the event of an SSR.
2053 Reduce the poll time to observe and deal with SSR faster.
2054 */
Ashish Jain5106d362016-05-11 19:23:33 +05302055 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002056 compress_set_max_poll_wait(out->compr, 1000);
2057 }
2058
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002059 audio_extn_dts_create_state_notifier_node(out->usecase);
2060 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2061 popcount(out->channel_mask),
2062 out->playback_started);
2063
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002064#ifdef DS1_DOLBY_DDP_ENABLED
2065 if (audio_extn_is_dolby_format(out->format))
2066 audio_extn_dolby_send_ddp_endp_params(adev);
2067#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302068 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002069 if (adev->visualizer_start_output != NULL)
2070 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2071 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302072 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002073 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002076
2077 if (ret == 0) {
2078 register_out_stream(out);
2079 if (out->realtime) {
2080 ret = pcm_start(out->pcm);
2081 if (ret < 0)
2082 goto error_open;
2083 }
2084 }
2085
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302086 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002087 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002088
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002089 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302091 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002093error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302094 /*
2095 * sleep 50ms to allow sufficient time for kernel
2096 * drivers to recover incases like SSR.
2097 */
2098 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002099 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100}
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102static int check_input_parameters(uint32_t sample_rate,
2103 audio_format_t format,
2104 int channel_count)
2105{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002106 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302108 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2109 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2110 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002111 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302112 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002113
2114 switch (channel_count) {
2115 case 1:
2116 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302117 case 3:
2118 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002119 case 6:
2120 break;
2121 default:
2122 ret = -EINVAL;
2123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
2125 switch (sample_rate) {
2126 case 8000:
2127 case 11025:
2128 case 12000:
2129 case 16000:
2130 case 22050:
2131 case 24000:
2132 case 32000:
2133 case 44100:
2134 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302135 case 96000:
2136 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 break;
2138 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002139 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 }
2141
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002142 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143}
2144
2145static size_t get_input_buffer_size(uint32_t sample_rate,
2146 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002147 int channel_count,
2148 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149{
2150 size_t size = 0;
2151
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002152 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2153 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002155 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002156 if (is_low_latency)
2157 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302158
2159 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002161 /* make sure the size is multiple of 32 bytes
2162 * At 48 kHz mono 16-bit PCM:
2163 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2164 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2165 */
2166 size += 0x1f;
2167 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002168
2169 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170}
2171
Ashish Jain5106d362016-05-11 19:23:33 +05302172static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2173{
2174 uint64_t actual_frames_rendered = 0;
2175 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2176
2177 /* This adjustment accounts for buffering after app processor.
2178 * It is based on estimated DSP latency per use case, rather than exact.
2179 */
2180 int64_t platform_latency = platform_render_latency(out->usecase) *
2181 out->sample_rate / 1000000LL;
2182
2183 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2184 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2185 * hence only estimate.
2186 */
2187 int64_t signed_frames = out->written - kernel_buffer_size;
2188
2189 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2190
2191 if (signed_frames > 0)
2192 actual_frames_rendered = signed_frames;
2193
2194 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2195 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2196 (long long int)out->written, (int)kernel_buffer_size,
2197 audio_bytes_per_sample(out->compr_config.codec->format),
2198 popcount(out->channel_mask));
2199
2200 return actual_frames_rendered;
2201}
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2204{
2205 struct stream_out *out = (struct stream_out *)stream;
2206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002210static int out_set_sample_rate(struct audio_stream *stream __unused,
2211 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212{
2213 return -ENOSYS;
2214}
2215
2216static size_t out_get_buffer_size(const struct audio_stream *stream)
2217{
2218 struct stream_out *out = (struct stream_out *)stream;
2219
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002220 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002222 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2223 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302224 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302225 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002227 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002228 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
2231static uint32_t out_get_channels(const struct audio_stream *stream)
2232{
2233 struct stream_out *out = (struct stream_out *)stream;
2234
2235 return out->channel_mask;
2236}
2237
2238static audio_format_t out_get_format(const struct audio_stream *stream)
2239{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 struct stream_out *out = (struct stream_out *)stream;
2241
2242 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243}
2244
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002245static int out_set_format(struct audio_stream *stream __unused,
2246 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247{
2248 return -ENOSYS;
2249}
2250
2251static int out_standby(struct audio_stream *stream)
2252{
2253 struct stream_out *out = (struct stream_out *)stream;
2254 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302256 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2257 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002259 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002261 if (adev->adm_deregister_stream)
2262 adev->adm_deregister_stream(adev->adm_data, out->handle);
2263
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002264 if (is_offload_usecase(out->usecase))
2265 stop_compressed_output_l(out);
2266
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002267 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002269 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2270 voice_extn_compress_voip_close_output_stream(stream);
2271 pthread_mutex_unlock(&adev->lock);
2272 pthread_mutex_unlock(&out->lock);
2273 ALOGD("VOIP output entered standby");
2274 return 0;
2275 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 if (out->pcm) {
2277 pcm_close(out->pcm);
2278 out->pcm = NULL;
2279 }
2280 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002281 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302282 out->send_next_track_params = false;
2283 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002284 out->gapless_mdata.encoder_delay = 0;
2285 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 if (out->compr != NULL) {
2287 compress_close(out->compr);
2288 out->compr = NULL;
2289 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002292 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 }
2294 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302295 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 return 0;
2297}
2298
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002299static int out_dump(const struct audio_stream *stream __unused,
2300 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301{
2302 return 0;
2303}
2304
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002305static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2306{
2307 int ret = 0;
2308 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002309
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002310 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002311 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002312 return -EINVAL;
2313 }
2314
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302315 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002316
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002317 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2318 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302319 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002320 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002321 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2322 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302323 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002324 }
2325
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326 ALOGV("%s new encoder delay %u and padding %u", __func__,
2327 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2328
2329 return 0;
2330}
2331
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002332static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2333{
2334 return out == adev->primary_output || out == adev->voice_tx_output;
2335}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340 struct audio_device *adev = out->dev;
2341 struct str_parms *parms;
2342 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002343 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
sangwoobc677242013-08-08 16:53:43 +09002345 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002346 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302348 if (!parms)
2349 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002350 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2351 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002353 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002354 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002356 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002357 * When HDMI cable is unplugged the music playback is paused and
2358 * the policy manager sends routing=0. But the audioflinger continues
2359 * to write data until standby time (3sec). As the HDMI core is
2360 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002361 * Avoid this by routing audio to speaker until standby.
2362 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002363 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2364 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302365 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002366 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2367 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002368 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302369 /*
2370 * When A2DP is disconnected the
2371 * music playback is paused and the policy manager sends routing=0
2372 * But the audioflingercontinues to write data until standby time
2373 * (3sec). As BT is turned off, the write gets blocked.
2374 * Avoid this by routing audio to speaker until standby.
2375 */
2376 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2377 (val == AUDIO_DEVICE_NONE)) {
2378 val = AUDIO_DEVICE_OUT_SPEAKER;
2379 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002380
2381 /*
2382 * select_devices() call below switches all the usecases on the same
2383 * backend to the new device. Refer to check_usecases_codec_backend() in
2384 * the select_devices(). But how do we undo this?
2385 *
2386 * For example, music playback is active on headset (deep-buffer usecase)
2387 * and if we go to ringtones and select a ringtone, low-latency usecase
2388 * will be started on headset+speaker. As we can't enable headset+speaker
2389 * and headset devices at the same time, select_devices() switches the music
2390 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2391 * So when the ringtone playback is completed, how do we undo the same?
2392 *
2393 * We are relying on the out_set_parameters() call on deep-buffer output,
2394 * once the ringtone playback is ended.
2395 * NOTE: We should not check if the current devices are same as new devices.
2396 * Because select_devices() must be called to switch back the music
2397 * playback to headset.
2398 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002399 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002400 audio_devices_t new_dev = val;
2401 bool same_dev = out->devices == new_dev;
2402 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002403
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002404 if (output_drives_call(adev, out)) {
2405 if(!voice_is_in_call(adev)) {
2406 if (adev->mode == AUDIO_MODE_IN_CALL) {
2407 adev->current_call_output = out;
2408 ret = voice_start_call(adev);
2409 }
2410 } else {
2411 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002412 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002413 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002414 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002415
2416 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002417 if (!same_dev) {
2418 ALOGV("update routing change");
2419 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302420 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2421 adev->perf_lock_opts,
2422 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002423 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002424 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302425 if (!same_dev)
2426 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002427 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002428 }
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002431 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002433
2434 if (out == adev->primary_output) {
2435 pthread_mutex_lock(&adev->lock);
2436 audio_extn_set_parameters(adev, parms);
2437 pthread_mutex_unlock(&adev->lock);
2438 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002439 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002440 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002441 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002442
2443 audio_extn_dts_create_state_notifier_node(out->usecase);
2444 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2445 popcount(out->channel_mask),
2446 out->playback_started);
2447
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002448 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002449 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302452error:
Eric Laurent994a6932013-07-17 11:51:42 -07002453 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454 return ret;
2455}
2456
2457static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2458{
2459 struct stream_out *out = (struct stream_out *)stream;
2460 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002461 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 char value[256];
2463 struct str_parms *reply = str_parms_create();
2464 size_t i, j;
2465 int ret;
2466 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002467
2468 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002469 if (reply) {
2470 str_parms_destroy(reply);
2471 }
2472 if (query) {
2473 str_parms_destroy(query);
2474 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002475 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2476 return NULL;
2477 }
2478
Eric Laurent994a6932013-07-17 11:51:42 -07002479 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2481 if (ret >= 0) {
2482 value[0] = '\0';
2483 i = 0;
2484 while (out->supported_channel_masks[i] != 0) {
2485 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2486 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2487 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002488 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002490 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 first = false;
2492 break;
2493 }
2494 }
2495 i++;
2496 }
2497 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2498 str = str_parms_to_str(reply);
2499 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002500 voice_extn_out_get_parameters(out, query, reply);
2501 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002502 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002503 free(str);
2504 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002507
Alexy Joseph62142aa2015-11-16 15:10:34 -08002508
2509 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2510 if (ret >= 0) {
2511 value[0] = '\0';
2512 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2513 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302514 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002515 } else {
2516 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302517 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002518 }
2519 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002520 if (str)
2521 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002522 str = str_parms_to_str(reply);
2523 }
2524
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002525 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2526 if (ret >= 0) {
2527 value[0] = '\0';
2528 i = 0;
2529 first = true;
2530 while (out->supported_formats[i] != 0) {
2531 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2532 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2533 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002534 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002535 }
2536 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2537 first = false;
2538 break;
2539 }
2540 }
2541 i++;
2542 }
2543 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002544 if (str)
2545 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002546 str = str_parms_to_str(reply);
2547 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002548
2549 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2550 if (ret >= 0) {
2551 value[0] = '\0';
2552 i = 0;
2553 first = true;
2554 while (out->supported_sample_rates[i] != 0) {
2555 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2556 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2557 if (!first) {
2558 strlcat(value, "|", sizeof(value));
2559 }
2560 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2561 first = false;
2562 break;
2563 }
2564 }
2565 i++;
2566 }
2567 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2568 if (str)
2569 free(str);
2570 str = str_parms_to_str(reply);
2571 }
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 str_parms_destroy(query);
2574 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002575 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 return str;
2577}
2578
2579static uint32_t out_get_latency(const struct audio_stream_out *stream)
2580{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002581 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002583 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Alexy Josephaa54c872014-12-03 02:46:47 -08002585 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002586 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002587 } else if (out->realtime) {
2588 // since the buffer won't be filled up faster than realtime,
2589 // return a smaller number
2590 if (out->config.rate)
2591 period_ms = (out->af_period_multiplier * out->config.period_size *
2592 1000) / (out->config.rate);
2593 else
2594 period_ms = 0;
2595 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002596 } else {
2597 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002599 }
2600
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302601 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002602 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603}
2604
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302605static float AmpToDb(float amplification)
2606{
2607 if (amplification == 0) {
2608 return DSD_VOLUME_MIN_DB;
2609 }
2610 return 20 * log10(amplification);
2611}
2612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613static int out_set_volume(struct audio_stream_out *stream, float left,
2614 float right)
2615{
Eric Laurenta9024de2013-04-04 09:19:12 -07002616 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 int volume[2];
2618
Eric Laurenta9024de2013-04-04 09:19:12 -07002619 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2620 /* only take left channel into account: the API is for stereo anyway */
2621 out->muted = (left == 0.0f);
2622 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002623 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302624 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002625 /*
2626 * Set mute or umute on HDMI passthrough stream.
2627 * Only take left channel into account.
2628 * Mute is 0 and unmute 1
2629 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302630 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302631 } else if (out->format == AUDIO_FORMAT_DSD){
2632 char mixer_ctl_name[128] = "DSD Volume";
2633 struct audio_device *adev = out->dev;
2634 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2635
2636 if (!ctl) {
2637 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2638 __func__, mixer_ctl_name);
2639 return -EINVAL;
2640 }
2641 volume[0] = (int)(AmpToDb(left));
2642 volume[1] = (int)(AmpToDb(right));
2643 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2644 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002645 } else {
2646 char mixer_ctl_name[128];
2647 struct audio_device *adev = out->dev;
2648 struct mixer_ctl *ctl;
2649 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002650 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002651
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002652 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2653 "Compress Playback %d Volume", pcm_device_id);
2654 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2655 if (!ctl) {
2656 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2657 __func__, mixer_ctl_name);
2658 return -EINVAL;
2659 }
2660 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2661 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2662 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2663 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002665 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 return -ENOSYS;
2668}
2669
2670static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2671 size_t bytes)
2672{
2673 struct stream_out *out = (struct stream_out *)stream;
2674 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302675 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002676 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002678 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302679
Naresh Tanniru80659832014-06-04 18:17:56 +05302680 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002681
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302682 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302683 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302684 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2685 pthread_mutex_unlock(&out->lock);
2686 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302687 } else {
2688 /* increase written size during SSR to avoid mismatch
2689 * with the written frames count in AF
2690 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002691 // bytes per frame
2692 size_t bpf = audio_bytes_per_sample(out->format) *
2693 audio_channel_count_from_out_mask(out->channel_mask);
2694 if (bpf != 0)
2695 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302696 ALOGD(" %s: sound card is not active/SSR state", __func__);
2697 ret= -EIO;
2698 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302699 }
2700 }
2701
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302702 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302703 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2704 if (audio_bytes_per_sample(out->format) != 0)
2705 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2706 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302707 goto exit;
2708 }
2709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002711 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002712 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002713 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2714 ret = voice_extn_compress_voip_start_output_stream(out);
2715 else
2716 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002717 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002718 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002720 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 goto exit;
2722 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002723
2724 if (last_known_cal_step != -1) {
2725 ALOGD("%s: retry previous failed cal level set", __func__);
2726 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729
Ashish Jain81eb2a82015-05-13 10:52:34 +05302730 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002731 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302732 adev->is_channel_status_set = true;
2733 }
2734
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002735 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002736 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002737 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002738 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002739 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2740 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302741 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2742 ALOGD("copl(%p):send next track params in gapless", out);
2743 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2744 out->send_next_track_params = false;
2745 out->is_compr_metadata_avail = false;
2746 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002747 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302748 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302749 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002750
Ashish Jain83a6cc22016-06-28 14:34:17 +05302751 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302752 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302753 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302754 pthread_mutex_unlock(&out->lock);
2755 return -EINVAL;
2756 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302757 audio_format_t dst_format = out->hal_op_format;
2758 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302759
2760 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2761 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2762
Ashish Jain83a6cc22016-06-28 14:34:17 +05302763 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302764 dst_format,
2765 buffer,
2766 src_format,
2767 frames);
2768
Ashish Jain83a6cc22016-06-28 14:34:17 +05302769 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302770 bytes_to_write);
2771
2772 /*Convert written bytes in audio flinger format*/
2773 if (ret > 0)
2774 ret = ((ret * format_to_bitwidth_table[out->format]) /
2775 format_to_bitwidth_table[dst_format]);
2776 }
2777 } else
2778 ret = compress_write(out->compr, buffer, bytes);
2779
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302780 if (ret < 0)
2781 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302782 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002783 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302784 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002785 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302786 } else if (-ENETRESET == ret) {
2787 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2788 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2789 pthread_mutex_unlock(&out->lock);
2790 out_standby(&out->stream.common);
2791 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002792 }
Ashish Jain5106d362016-05-11 19:23:33 +05302793 if ( ret == (ssize_t)bytes && !out->non_blocking)
2794 out->written += bytes;
2795
Naresh Tanniru80659832014-06-04 18:17:56 +05302796 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002797 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002798 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->playback_started = 1;
2800 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002801
2802 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2803 popcount(out->channel_mask),
2804 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 }
2806 pthread_mutex_unlock(&out->lock);
2807 return ret;
2808 } else {
2809 if (out->pcm) {
2810 if (out->muted)
2811 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002812
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302813 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002814
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002815 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002816
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002817 if (out->config.rate)
2818 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2819 out->config.rate;
2820
2821 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2822
2823 request_out_focus(out, ns);
2824
2825 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002826 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002827 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302828 out->convert_buffer != NULL) {
2829
2830 memcpy_by_audio_format(out->convert_buffer,
2831 out->hal_op_format,
2832 buffer,
2833 out->hal_ip_format,
2834 out->config.period_size * out->config.channels);
2835
2836 ret = pcm_write(out->pcm, out->convert_buffer,
2837 (out->config.period_size *
2838 out->config.channels *
2839 format_to_bitwidth_table[out->hal_op_format]));
2840 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002841 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302842 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002843
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002844 release_out_focus(out);
2845
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302846 if (ret < 0)
2847 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302848 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2849 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2850 else
2851 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 }
2854
2855exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302856 /* ToDo: There may be a corner case when SSR happens back to back during
2857 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302858 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302859 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302860 }
2861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 pthread_mutex_unlock(&out->lock);
2863
2864 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002865 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002866 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302867 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302868 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302869 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302870 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302871 out->standby = true;
2872 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302874 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302875 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 }
2877 return bytes;
2878}
2879
2880static int out_get_render_position(const struct audio_stream_out *stream,
2881 uint32_t *dsp_frames)
2882{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302884 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002885
2886 if (dsp_frames == NULL)
2887 return -EINVAL;
2888
2889 *dsp_frames = 0;
2890 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002891 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302892
2893 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2894 * this operation and adev_close_output_stream(where out gets reset).
2895 */
2896 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2897 *dsp_frames = get_actual_pcm_frames_rendered(out);
2898 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2899 return 0;
2900 }
2901
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002902 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302903 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302904 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302906 if (ret < 0)
2907 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302909 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 }
2911 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302912 if (-ENETRESET == ret) {
2913 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2914 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2915 return -EINVAL;
2916 } else if(ret < 0) {
2917 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2918 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302919 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2920 /*
2921 * Handle corner case where compress session is closed during SSR
2922 * and timestamp is queried
2923 */
2924 ALOGE(" ERROR: sound card not active, return error");
2925 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302926 } else {
2927 return 0;
2928 }
Zhou Song32a556e2015-05-05 10:46:56 +08002929 } else if (audio_is_linear_pcm(out->format)) {
2930 *dsp_frames = out->written;
2931 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002932 } else
2933 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934}
2935
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002936static int out_add_audio_effect(const struct audio_stream *stream __unused,
2937 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938{
2939 return 0;
2940}
2941
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002942static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2943 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944{
2945 return 0;
2946}
2947
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002948static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2949 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950{
2951 return -EINVAL;
2952}
2953
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002954static int out_get_presentation_position(const struct audio_stream_out *stream,
2955 uint64_t *frames, struct timespec *timestamp)
2956{
2957 struct stream_out *out = (struct stream_out *)stream;
2958 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002959 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002960
Ashish Jain5106d362016-05-11 19:23:33 +05302961 /* below piece of code is not guarded against any lock because audioFliner serializes
2962 * this operation and adev_close_output_stream( where out gets reset).
2963 */
2964 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2965 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2966 *frames = get_actual_pcm_frames_rendered(out);
2967 /* this is the best we can do */
2968 clock_gettime(CLOCK_MONOTONIC, timestamp);
2969 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2970 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2971 return 0;
2972 }
2973
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002974 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002975
Ashish Jain5106d362016-05-11 19:23:33 +05302976 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2977 ret = compress_get_tstamp(out->compr, &dsp_frames,
2978 &out->sample_rate);
2979 ALOGVV("%s rendered frames %ld sample_rate %d",
2980 __func__, dsp_frames, out->sample_rate);
2981 *frames = dsp_frames;
2982 if (ret < 0)
2983 ret = -errno;
2984 if (-ENETRESET == ret) {
2985 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2986 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2987 ret = -EINVAL;
2988 } else
2989 ret = 0;
2990 /* this is the best we can do */
2991 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002992 } else {
2993 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002994 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002995 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2996 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002997 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002998 // This adjustment accounts for buffering after app processor.
2999 // It is based on estimated DSP latency per use case, rather than exact.
3000 signed_frames -=
3001 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3002
Eric Laurent949a0892013-09-20 09:20:13 -07003003 // It would be unusual for this value to be negative, but check just in case ...
3004 if (signed_frames >= 0) {
3005 *frames = signed_frames;
3006 ret = 0;
3007 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003008 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303009 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3010 *frames = out->written;
3011 clock_gettime(CLOCK_MONOTONIC, timestamp);
3012 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003013 }
3014 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003015 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003016 return ret;
3017}
3018
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003019static int out_set_callback(struct audio_stream_out *stream,
3020 stream_callback_t callback, void *cookie)
3021{
3022 struct stream_out *out = (struct stream_out *)stream;
3023
3024 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003025 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 out->offload_callback = callback;
3027 out->offload_cookie = cookie;
3028 pthread_mutex_unlock(&out->lock);
3029 return 0;
3030}
3031
3032static int out_pause(struct audio_stream_out* stream)
3033{
3034 struct stream_out *out = (struct stream_out *)stream;
3035 int status = -ENOSYS;
3036 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003037 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003038 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003039 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303041 struct audio_device *adev = out->dev;
3042 int snd_scard_state = get_snd_card_state(adev);
3043
3044 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3045 status = compress_pause(out->compr);
3046
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003048
Mingming Yin21854652016-04-13 11:54:02 -07003049 if (audio_extn_passthru_is_active()) {
3050 ALOGV("offload use case, pause passthru");
3051 audio_extn_passthru_on_pause(out);
3052 }
3053
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303054 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003055 audio_extn_dts_notify_playback_state(out->usecase, 0,
3056 out->sample_rate, popcount(out->channel_mask),
3057 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 }
3059 pthread_mutex_unlock(&out->lock);
3060 }
3061 return status;
3062}
3063
3064static int out_resume(struct audio_stream_out* stream)
3065{
3066 struct stream_out *out = (struct stream_out *)stream;
3067 int status = -ENOSYS;
3068 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003069 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003070 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003072 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303074 struct audio_device *adev = out->dev;
3075 int snd_scard_state = get_snd_card_state(adev);
3076
Mingming Yin21854652016-04-13 11:54:02 -07003077 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3078 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3079 pthread_mutex_lock(&out->dev->lock);
3080 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003081 pthread_mutex_unlock(&out->dev->lock);
3082 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303083 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003084 }
3085 if (!status) {
3086 out->offload_state = OFFLOAD_STATE_PLAYING;
3087 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303088 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003089 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3090 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 }
3092 pthread_mutex_unlock(&out->lock);
3093 }
3094 return status;
3095}
3096
3097static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3098{
3099 struct stream_out *out = (struct stream_out *)stream;
3100 int status = -ENOSYS;
3101 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003102 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003103 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3105 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3106 else
3107 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3108 pthread_mutex_unlock(&out->lock);
3109 }
3110 return status;
3111}
3112
3113static int out_flush(struct audio_stream_out* stream)
3114{
3115 struct stream_out *out = (struct stream_out *)stream;
3116 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003117 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003118 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003119 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303121 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003123 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 return 0;
3125 }
3126 return -ENOSYS;
3127}
3128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129/** audio_stream_in implementation **/
3130static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3131{
3132 struct stream_in *in = (struct stream_in *)stream;
3133
3134 return in->config.rate;
3135}
3136
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003137static int in_set_sample_rate(struct audio_stream *stream __unused,
3138 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139{
3140 return -ENOSYS;
3141}
3142
3143static size_t in_get_buffer_size(const struct audio_stream *stream)
3144{
3145 struct stream_in *in = (struct stream_in *)stream;
3146
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003147 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3148 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003149 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3150 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003151
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003152 return in->config.period_size * in->af_period_multiplier *
3153 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
3156static uint32_t in_get_channels(const struct audio_stream *stream)
3157{
3158 struct stream_in *in = (struct stream_in *)stream;
3159
3160 return in->channel_mask;
3161}
3162
3163static audio_format_t in_get_format(const struct audio_stream *stream)
3164{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003165 struct stream_in *in = (struct stream_in *)stream;
3166
3167 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168}
3169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003170static int in_set_format(struct audio_stream *stream __unused,
3171 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172{
3173 return -ENOSYS;
3174}
3175
3176static int in_standby(struct audio_stream *stream)
3177{
3178 struct stream_in *in = (struct stream_in *)stream;
3179 struct audio_device *adev = in->dev;
3180 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303181 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3182 stream, in->usecase, use_case_table[in->usecase]);
3183
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003184 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003185 if (!in->standby && in->is_st_session) {
3186 ALOGD("%s: sound trigger pcm stop lab", __func__);
3187 audio_extn_sound_trigger_stop_lab(in);
3188 in->standby = 1;
3189 }
3190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003192 if (adev->adm_deregister_stream)
3193 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3194
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003195 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003197 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3198 voice_extn_compress_voip_close_input_stream(stream);
3199 ALOGD("VOIP input entered standby");
3200 } else {
3201 if (in->pcm) {
3202 pcm_close(in->pcm);
3203 in->pcm = NULL;
3204 }
3205 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003206 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003207 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 }
3209 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003210 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 return status;
3212}
3213
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003214static int in_dump(const struct audio_stream *stream __unused,
3215 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216{
3217 return 0;
3218}
3219
3220static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3221{
3222 struct stream_in *in = (struct stream_in *)stream;
3223 struct audio_device *adev = in->dev;
3224 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003226 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303228 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 parms = str_parms_create_str(kvpairs);
3230
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303231 if (!parms)
3232 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003233 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003234 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003235
3236 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3237 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 val = atoi(value);
3239 /* no audio source uses val == 0 */
3240 if ((in->source != val) && (val != 0)) {
3241 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003242 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3243 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3244 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003245 (in->config.rate == 8000 || in->config.rate == 16000 ||
3246 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003247 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003248 err = voice_extn_compress_voip_open_input_stream(in);
3249 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003250 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003251 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003252 }
3253 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 }
3255 }
3256
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003257 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3258 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003260 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 in->device = val;
3262 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003263 if (!in->standby && !in->is_st_session) {
3264 ALOGV("update input routing change");
3265 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003266 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003267 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 }
3269 }
3270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003272 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273
3274 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303275error:
Eric Laurent994a6932013-07-17 11:51:42 -07003276 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 return ret;
3278}
3279
3280static char* in_get_parameters(const struct audio_stream *stream,
3281 const char *keys)
3282{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003283 struct stream_in *in = (struct stream_in *)stream;
3284 struct str_parms *query = str_parms_create_str(keys);
3285 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003286 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003287
3288 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003289 if (reply) {
3290 str_parms_destroy(reply);
3291 }
3292 if (query) {
3293 str_parms_destroy(query);
3294 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003295 ALOGE("in_get_parameters: failed to create query or reply");
3296 return NULL;
3297 }
3298
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003299 ALOGV("%s: enter: keys - %s", __func__, keys);
3300
3301 voice_extn_in_get_parameters(in, query, reply);
3302
3303 str = str_parms_to_str(reply);
3304 str_parms_destroy(query);
3305 str_parms_destroy(reply);
3306
3307 ALOGV("%s: exit: returns - %s", __func__, str);
3308 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309}
3310
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003311static int in_set_gain(struct audio_stream_in *stream __unused,
3312 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return 0;
3315}
3316
3317static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3318 size_t bytes)
3319{
3320 struct stream_in *in = (struct stream_in *)stream;
3321 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303322 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303324 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303327
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003328 if (in->is_st_session) {
3329 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3330 /* Read from sound trigger HAL */
3331 audio_extn_sound_trigger_read(in, buffer, bytes);
3332 pthread_mutex_unlock(&in->lock);
3333 return bytes;
3334 }
3335
Ashish Jainbbce4322016-02-16 13:25:27 +05303336 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003337 ALOGD(" %s: sound card is not active/SSR state", __func__);
3338 ret= -EIO;;
3339 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303340 }
3341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003343 pthread_mutex_lock(&adev->lock);
3344 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3345 ret = voice_extn_compress_voip_start_input_stream(in);
3346 else
3347 ret = start_input_stream(in);
3348 pthread_mutex_unlock(&adev->lock);
3349 if (ret != 0) {
3350 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 }
3352 in->standby = 0;
3353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003355 // what's the duration requested by the client?
3356 long ns = 0;
3357
3358 if (in->config.rate)
3359 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3360 in->config.rate;
3361
3362 request_in_focus(in, ns);
3363 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303366 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003367 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303368 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003369 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003370 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003371 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303372 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003373 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303374 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3375 if (bytes % 4 == 0) {
3376 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3377 int_buf_stream = buffer;
3378 for (size_t itt=0; itt < bytes/4 ; itt++) {
3379 int_buf_stream[itt] >>= 8;
3380 }
3381 } else {
3382 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3383 ret = -EINVAL;
3384 goto exit;
3385 }
3386 } if (ret < 0) {
3387 ret = -errno;
3388 }
3389 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 }
3391
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003392 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 /*
3395 * Instead of writing zeroes here, we could trust the hardware
3396 * to always provide zeroes when muted.
3397 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303398 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3399 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 memset(buffer, 0, bytes);
3401
3402exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303403 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303404 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003405 if (-ENETRESET == ret)
3406 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 pthread_mutex_unlock(&in->lock);
3409
3410 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303411 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303412 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303413 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303414 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303415 in->standby = true;
3416 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303417 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003419 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303420 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303421 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 }
3423 return bytes;
3424}
3425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427{
3428 return 0;
3429}
3430
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003431static int add_remove_audio_effect(const struct audio_stream *stream,
3432 effect_handle_t effect,
3433 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003435 struct stream_in *in = (struct stream_in *)stream;
3436 int status = 0;
3437 effect_descriptor_t desc;
3438
3439 status = (*effect)->get_descriptor(effect, &desc);
3440 if (status != 0)
3441 return status;
3442
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003443 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003444 pthread_mutex_lock(&in->dev->lock);
3445 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3446 in->enable_aec != enable &&
3447 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3448 in->enable_aec = enable;
3449 if (!in->standby)
3450 select_devices(in->dev, in->usecase);
3451 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003452 if (in->enable_ns != enable &&
3453 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3454 in->enable_ns = enable;
3455 if (!in->standby)
3456 select_devices(in->dev, in->usecase);
3457 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003458 pthread_mutex_unlock(&in->dev->lock);
3459 pthread_mutex_unlock(&in->lock);
3460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 return 0;
3462}
3463
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003464static int in_add_audio_effect(const struct audio_stream *stream,
3465 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466{
Eric Laurent994a6932013-07-17 11:51:42 -07003467 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003468 return add_remove_audio_effect(stream, effect, true);
3469}
3470
3471static int in_remove_audio_effect(const struct audio_stream *stream,
3472 effect_handle_t effect)
3473{
Eric Laurent994a6932013-07-17 11:51:42 -07003474 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003475 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476}
3477
3478static int adev_open_output_stream(struct audio_hw_device *dev,
3479 audio_io_handle_t handle,
3480 audio_devices_t devices,
3481 audio_output_flags_t flags,
3482 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003483 struct audio_stream_out **stream_out,
3484 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485{
3486 struct audio_device *adev = (struct audio_device *)dev;
3487 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303488 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003489 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303492
3493 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3494 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003495 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303496 return -EINVAL;
3497 }
3498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3500
Mingming Yin3a941d42016-02-17 18:08:05 -08003501 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3502 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303503 devices, flags, &out->stream);
3504
3505
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003506 if (!out) {
3507 return -ENOMEM;
3508 }
3509
Haynes Mathew George204045b2015-02-25 20:32:03 -08003510 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003511 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003512 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 if (devices == AUDIO_DEVICE_NONE)
3515 devices = AUDIO_DEVICE_OUT_SPEAKER;
3516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 out->flags = flags;
3518 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003519 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003520 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003521 out->sample_rate = config->sample_rate;
3522 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3523 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003524 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003525 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003526 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303527 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Mingming Yin3a941d42016-02-17 18:08:05 -08003529 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3530 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3531 pthread_mutex_lock(&adev->lock);
3532 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3533 ret = read_hdmi_sink_caps(out);
3534 pthread_mutex_unlock(&adev->lock);
3535 if (ret != 0) {
3536 if (ret == -ENOSYS) {
3537 /* ignore and go with default */
3538 ret = 0;
3539 } else {
3540 ALOGE("error reading hdmi sink caps");
3541 goto error_open;
3542 }
3543 }
3544 }
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003547 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303548 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3549 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003550 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3551 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3552
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003553 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003554 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3555 /*
3556 * Do not handle stereo output in Multi-channel cases
3557 * Stereo case is handled in normal playback path
3558 */
3559 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3560 ret = AUDIO_CHANNEL_OUT_STEREO;
3561 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003562
3563 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3564 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003565 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003566 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003567 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003568
3569 if (config->sample_rate == 0)
3570 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3571 if (config->channel_mask == 0)
3572 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003573 if (config->format == 0)
3574 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003575
3576 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003578 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3580 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003582 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003584 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3585 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003586 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003587 ret = voice_extn_compress_voip_open_output_stream(out);
3588 if (ret != 0) {
3589 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3590 __func__, ret);
3591 goto error_open;
3592 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003593 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3594 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3595
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3597 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3598 ALOGE("%s: Unsupported Offload information", __func__);
3599 ret = -EINVAL;
3600 goto error_open;
3601 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003602
Mingming Yin3a941d42016-02-17 18:08:05 -08003603 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003604 if(config->offload_info.format == 0)
3605 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003606 if (config->offload_info.sample_rate == 0)
3607 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003608 }
3609
Mingming Yin90310102013-11-13 16:57:00 -08003610 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303611 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003612 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 ret = -EINVAL;
3614 goto error_open;
3615 }
3616
3617 out->compr_config.codec = (struct snd_codec *)
3618 calloc(1, sizeof(struct snd_codec));
3619
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003620 if (!out->compr_config.codec) {
3621 ret = -ENOMEM;
3622 goto error_open;
3623 }
3624
vivek mehta0ea887a2015-08-26 14:01:20 -07003625 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303626 out->stream.pause = out_pause;
3627 out->stream.flush = out_flush;
3628 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003629 out->usecase = get_offload_usecase(adev, true);
3630 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003631 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003632 out->stream.set_callback = out_set_callback;
3633 out->stream.pause = out_pause;
3634 out->stream.resume = out_resume;
3635 out->stream.drain = out_drain;
3636 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003637 out->usecase = get_offload_usecase(adev, false);
3638 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003639 }
vivek mehta446c3962015-09-14 10:57:35 -07003640
3641 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003642 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3643 config->format == 0 && config->sample_rate == 0 &&
3644 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003645 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003646 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3647 } else {
3648 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3649 ret = -EEXIST;
3650 goto error_open;
3651 }
vivek mehta446c3962015-09-14 10:57:35 -07003652 }
3653
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 if (config->offload_info.channel_mask)
3655 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003656 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003657 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003658 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003659 } else {
3660 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3661 ret = -EINVAL;
3662 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003663 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003664
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003665 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 out->sample_rate = config->offload_info.sample_rate;
3667
Mingming Yin3ee55c62014-08-04 14:23:35 -07003668 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303670 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3671 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3672 audio_extn_dolby_send_ddp_endp_params(adev);
3673 audio_extn_dolby_set_dmid(adev);
3674 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003675
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003677 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 out->compr_config.codec->bit_rate =
3679 config->offload_info.bit_rate;
3680 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303681 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303683 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003684 /*TODO: Do we need to change it for passthrough */
3685 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686
Manish Dewangana6fc5442015-08-24 20:30:31 +05303687 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3688 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3689 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3690 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303691
3692 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3693 AUDIO_FORMAT_PCM) {
3694
3695 /*Based on platform support, configure appropriate alsa format for corresponding
3696 *hal input format.
3697 */
3698 out->compr_config.codec->format = hal_format_to_alsa(
3699 config->offload_info.format);
3700
Ashish Jain83a6cc22016-06-28 14:34:17 +05303701 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303702 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303703 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303704
3705 /*for direct PCM playback populate bit_width based on selected alsa format as
3706 *hal input format and alsa format might differ based on platform support.
3707 */
3708 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303709 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303710
3711 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3712
3713 /* Check if alsa session is configured with the same format as HAL input format,
3714 * if not then derive correct fragment size needed to accomodate the
3715 * conversion of HAL input format to alsa format.
3716 */
3717 audio_extn_utils_update_direct_pcm_fragment_size(out);
3718
3719 /*if hal input and output fragment size is different this indicates HAL input format is
3720 *not same as the alsa format
3721 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303722 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303723 /*Allocate a buffer to convert input data to the alsa configured format.
3724 *size of convert buffer is equal to the size required to hold one fragment size
3725 *worth of pcm data, this is because flinger does not write more than fragment_size
3726 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303727 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3728 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303729 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3730 ret = -ENOMEM;
3731 goto error_open;
3732 }
3733 }
3734 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3735 out->compr_config.fragment_size =
3736 audio_extn_passthru_get_buffer_size(&config->offload_info);
3737 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3738 } else {
3739 out->compr_config.fragment_size =
3740 platform_get_compress_offload_buffer_size(&config->offload_info);
3741 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3742 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003743
Amit Shekhar6f461b12014-08-01 14:52:58 -07003744 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303745 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003746
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003747 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3748 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003749
Alexy Josephaa54c872014-12-03 02:46:47 -08003750
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003751 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303752 out->send_next_track_params = false;
3753 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003754 out->offload_state = OFFLOAD_STATE_IDLE;
3755 out->playback_started = 0;
3756
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003757 audio_extn_dts_create_state_notifier_node(out->usecase);
3758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003759 create_offload_callback_thread(out);
3760 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3761 __func__, config->offload_info.version,
3762 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303763
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303764 /*Check if DSD audio format is supported in codec
3765 *and there is no active native DSD use case
3766 */
3767
3768 if ((config->format == AUDIO_FORMAT_DSD) &&
3769 (!platform_check_codec_dsd_support(adev->platform) ||
3770 audio_is_dsd_native_stream_active(adev))) {
3771 ret = -EINVAL;
3772 goto error_open;
3773 }
3774
Ashish Jain5106d362016-05-11 19:23:33 +05303775 /* Disable gapless if any of the following is true
3776 * passthrough playback
3777 * AV playback
3778 * Direct PCM playback
3779 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303780 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303781 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303782 config->offload_info.has_video ||
3783 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3784 check_and_set_gapless_mode(adev, false);
3785 } else
3786 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003787
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303788 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003789 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3790 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303791 if (config->format == AUDIO_FORMAT_DSD) {
3792 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3793 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3794 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003795 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303796 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003797 if (ret != 0) {
3798 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3799 __func__, ret);
3800 goto error_open;
3801 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003802 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3803 if (config->sample_rate == 0)
3804 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3805 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3806 config->sample_rate != 8000) {
3807 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3808 ret = -EINVAL;
3809 goto error_open;
3810 }
3811 out->sample_rate = config->sample_rate;
3812 out->config.rate = config->sample_rate;
3813 if (config->format == AUDIO_FORMAT_DEFAULT)
3814 config->format = AUDIO_FORMAT_PCM_16_BIT;
3815 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3816 config->format = AUDIO_FORMAT_PCM_16_BIT;
3817 ret = -EINVAL;
3818 goto error_open;
3819 }
3820 out->format = config->format;
3821 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3822 out->config = pcm_config_afe_proxy_playback;
3823 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003824 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303825 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3826 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003827 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3828 out->flags);
3829 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303830 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3831 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3832 out->config = pcm_config_low_latency;
3833 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3834 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3835 out->config = pcm_config_deep_buffer;
3836 } else {
3837 /* primary path is the default path selected if no other outputs are available/suitable */
3838 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3839 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3840 }
3841 out->hal_ip_format = format = out->format;
3842 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3843 out->hal_op_format = pcm_format_to_hal(out->config.format);
3844 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3845 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003846 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303847 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3848 if (out->hal_ip_format != out->hal_op_format) {
3849 uint32_t buffer_size = out->config.period_size *
3850 format_to_bitwidth_table[out->hal_op_format] *
3851 out->config.channels;
3852 out->convert_buffer = calloc(1, buffer_size);
3853 if (out->convert_buffer == NULL){
3854 ALOGE("Allocation failed for convert buffer for size %d",
3855 out->compr_config.fragment_size);
3856 ret = -ENOMEM;
3857 goto error_open;
3858 }
3859 ALOGD("Convert buffer allocated of size %d", buffer_size);
3860 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 }
3862
Ashish Jain83a6cc22016-06-28 14:34:17 +05303863 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3864 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3865
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003866 /* TODO remove this hardcoding and check why width is zero*/
3867 if (out->bit_width == 0)
3868 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003869 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3870 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003871 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303872 out->bit_width, out->channel_mask,
3873 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003874 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3875 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3876 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003877 if(adev->primary_output == NULL)
3878 adev->primary_output = out;
3879 else {
3880 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003881 ret = -EEXIST;
3882 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003883 }
3884 }
3885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 /* Check if this usecase is already existing */
3887 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003888 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3889 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003892 ret = -EEXIST;
3893 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 }
3895 pthread_mutex_unlock(&adev->lock);
3896
3897 out->stream.common.get_sample_rate = out_get_sample_rate;
3898 out->stream.common.set_sample_rate = out_set_sample_rate;
3899 out->stream.common.get_buffer_size = out_get_buffer_size;
3900 out->stream.common.get_channels = out_get_channels;
3901 out->stream.common.get_format = out_get_format;
3902 out->stream.common.set_format = out_set_format;
3903 out->stream.common.standby = out_standby;
3904 out->stream.common.dump = out_dump;
3905 out->stream.common.set_parameters = out_set_parameters;
3906 out->stream.common.get_parameters = out_get_parameters;
3907 out->stream.common.add_audio_effect = out_add_audio_effect;
3908 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3909 out->stream.get_latency = out_get_latency;
3910 out->stream.set_volume = out_set_volume;
3911 out->stream.write = out_write;
3912 out->stream.get_render_position = out_get_render_position;
3913 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003914 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003916 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003918 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003919 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920
3921 config->format = out->stream.common.get_format(&out->stream.common);
3922 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3923 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3924
3925 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303926 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003927 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003928
3929 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3930 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3931 popcount(out->channel_mask), out->playback_started);
3932
Eric Laurent994a6932013-07-17 11:51:42 -07003933 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003935
3936error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303937 if (out->convert_buffer)
3938 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003939 free(out);
3940 *stream_out = NULL;
3941 ALOGD("%s: exit: ret %d", __func__, ret);
3942 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943}
3944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003945static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 struct audio_stream_out *stream)
3947{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 struct stream_out *out = (struct stream_out *)stream;
3949 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003950 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303952 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3953
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003954 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303955 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003956 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303957 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003958 if(ret != 0)
3959 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3960 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003961 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003962 out_standby(&stream->common);
3963
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003964 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003965 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003966 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003967 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003968 if (out->compr_config.codec != NULL)
3969 free(out->compr_config.codec);
3970 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003971
Ashish Jain83a6cc22016-06-28 14:34:17 +05303972 if (out->convert_buffer != NULL) {
3973 free(out->convert_buffer);
3974 out->convert_buffer = NULL;
3975 }
3976
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003977 if (adev->voice_tx_output == out)
3978 adev->voice_tx_output = NULL;
3979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003980 pthread_cond_destroy(&out->cond);
3981 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003983 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984}
3985
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003986static void close_compress_sessions(struct audio_device *adev)
3987{
Mingming Yin7b762e72015-03-04 13:47:32 -08003988 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303989 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003990 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003991 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303992
3993 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003994 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303995 if (is_offload_usecase(usecase->id)) {
3996 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003997 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3998 out = usecase->stream.out;
3999 pthread_mutex_unlock(&adev->lock);
4000 out_standby(&out->stream.common);
4001 pthread_mutex_lock(&adev->lock);
4002 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304003 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004004 }
4005 pthread_mutex_unlock(&adev->lock);
4006}
4007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4009{
4010 struct audio_device *adev = (struct audio_device *)dev;
4011 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004013 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004014 int ret;
4015 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004017 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304020 if (!parms)
4021 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004022 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4023 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304024 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304025 if (strstr(snd_card_status, "OFFLINE")) {
4026 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304027 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004028 //close compress sessions on OFFLINE status
4029 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304030 } else if (strstr(snd_card_status, "ONLINE")) {
4031 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304032 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004033 //send dts hpx license if enabled
4034 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304035 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304036 }
4037
4038 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004039 status = voice_set_parameters(adev, parms);
4040 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004041 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004043 status = platform_set_parameters(adev->platform, parms);
4044 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004045 goto done;
4046
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004047 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4048 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004049 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4051 adev->bluetooth_nrec = true;
4052 else
4053 adev->bluetooth_nrec = false;
4054 }
4055
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004056 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4057 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4059 adev->screen_off = false;
4060 else
4061 adev->screen_off = true;
4062 }
4063
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004064 ret = str_parms_get_int(parms, "rotation", &val);
4065 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004066 bool reverse_speakers = false;
4067 switch(val) {
4068 // FIXME: note that the code below assumes that the speakers are in the correct placement
4069 // relative to the user when the device is rotated 90deg from its default rotation. This
4070 // assumption is device-specific, not platform-specific like this code.
4071 case 270:
4072 reverse_speakers = true;
4073 break;
4074 case 0:
4075 case 90:
4076 case 180:
4077 break;
4078 default:
4079 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004080 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004081 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004082 if (status == 0) {
4083 if (adev->speaker_lr_swap != reverse_speakers) {
4084 adev->speaker_lr_swap = reverse_speakers;
4085 // only update the selected device if there is active pcm playback
4086 struct audio_usecase *usecase;
4087 struct listnode *node;
4088 list_for_each(node, &adev->usecase_list) {
4089 usecase = node_to_item(node, struct audio_usecase, list);
4090 if (usecase->type == PCM_PLAYBACK) {
4091 select_devices(adev, usecase->id);
4092 break;
4093 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004094 }
4095 }
4096 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004097 }
4098
Mingming Yin514a8bc2014-07-29 15:22:21 -07004099 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4100 if (ret >= 0) {
4101 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4102 adev->bt_wb_speech_enabled = true;
4103 else
4104 adev->bt_wb_speech_enabled = false;
4105 }
4106
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004107 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4108 if (ret >= 0) {
4109 val = atoi(value);
4110 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4111 ALOGV("cache new edid");
4112 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004113 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4114 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004115 /*
4116 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4117 * Per AudioPolicyManager, USB device is higher priority than WFD.
4118 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4119 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4120 * starting voice call on USB
4121 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004122 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4123 if (ret >= 0) {
4124 audio_extn_usb_add_device(val, atoi(value));
4125 }
vivek mehta344576a2016-04-12 18:56:03 -07004126 ALOGV("detected USB connect .. disable proxy");
4127 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004128 }
4129 }
4130
4131 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4132 if (ret >= 0) {
4133 val = atoi(value);
4134 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4135 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004136 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004137 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4138 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4139 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4140 if (ret >= 0) {
4141 audio_extn_usb_remove_device(val, atoi(value));
4142 }
vivek mehta344576a2016-04-12 18:56:03 -07004143 ALOGV("detected USB disconnect .. enable proxy");
4144 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004145 }
4146 }
4147
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004148 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304149 // reconfigure should be done only after updating a2dpstate in audio extn
4150 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4151 if (ret >= 0) {
4152 struct audio_usecase *usecase;
4153 struct listnode *node;
4154 list_for_each(node, &adev->usecase_list) {
4155 usecase = node_to_item(node, struct audio_usecase, list);
4156 if ((usecase->type == PCM_PLAYBACK) &&
4157 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4158 ALOGD("reconfigure a2dp... forcing device switch");
4159 //force device switch to re configure encoder
4160 select_devices(adev, usecase->id);
4161 break;
4162 }
4163 }
4164 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004165
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004166done:
4167 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004168 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304169error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004170 ALOGV("%s: exit with code(%d)", __func__, status);
4171 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172}
4173
4174static char* adev_get_parameters(const struct audio_hw_device *dev,
4175 const char *keys)
4176{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004177 struct audio_device *adev = (struct audio_device *)dev;
4178 struct str_parms *reply = str_parms_create();
4179 struct str_parms *query = str_parms_create_str(keys);
4180 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304181 char value[256] = {0};
4182 int ret = 0;
4183
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004184 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004185 if (reply) {
4186 str_parms_destroy(reply);
4187 }
4188 if (query) {
4189 str_parms_destroy(query);
4190 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004191 ALOGE("adev_get_parameters: failed to create query or reply");
4192 return NULL;
4193 }
4194
Naresh Tannirud7205b62014-06-20 02:54:48 +05304195 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4196 sizeof(value));
4197 if (ret >=0) {
4198 int val = 1;
4199 pthread_mutex_lock(&adev->snd_card_status.lock);
4200 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4201 val = 0;
4202 pthread_mutex_unlock(&adev->snd_card_status.lock);
4203 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4204 goto exit;
4205 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004206
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004207 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004208 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004209 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004210 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304211 pthread_mutex_unlock(&adev->lock);
4212
Naresh Tannirud7205b62014-06-20 02:54:48 +05304213exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004214 str = str_parms_to_str(reply);
4215 str_parms_destroy(query);
4216 str_parms_destroy(reply);
4217
4218 ALOGV("%s: exit: returns - %s", __func__, str);
4219 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220}
4221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004222static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223{
4224 return 0;
4225}
4226
4227static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4228{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004229 int ret;
4230 struct audio_device *adev = (struct audio_device *)dev;
4231 pthread_mutex_lock(&adev->lock);
4232 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004233 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004234 pthread_mutex_unlock(&adev->lock);
4235 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236}
4237
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004238static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4239 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240{
4241 return -ENOSYS;
4242}
4243
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004244static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4245 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246{
4247 return -ENOSYS;
4248}
4249
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004250static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4251 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252{
4253 return -ENOSYS;
4254}
4255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004256static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4257 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258{
4259 return -ENOSYS;
4260}
4261
4262static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4263{
4264 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266 pthread_mutex_lock(&adev->lock);
4267 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004268 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004270 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004271 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004272 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004273 adev->current_call_output = NULL;
4274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275 }
4276 pthread_mutex_unlock(&adev->lock);
4277 return 0;
4278}
4279
4280static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4281{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004282 int ret;
4283
4284 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004285 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004286 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4287 pthread_mutex_unlock(&adev->lock);
4288
4289 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290}
4291
4292static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4293{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004294 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295 return 0;
4296}
4297
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004298static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 const struct audio_config *config)
4300{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004301 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004303 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4304 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305}
4306
4307static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004308 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 audio_devices_t devices,
4310 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004311 struct audio_stream_in **stream_in,
4312 audio_input_flags_t flags __unused,
4313 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004314 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315{
4316 struct audio_device *adev = (struct audio_device *)dev;
4317 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004318 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004319 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004320 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304323 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4324 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304326 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327
4328 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004329
4330 if (!in) {
4331 ALOGE("failed to allocate input stream");
4332 return -ENOMEM;
4333 }
4334
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304335 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304336 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4337 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004338 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004339 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 in->stream.common.get_sample_rate = in_get_sample_rate;
4342 in->stream.common.set_sample_rate = in_set_sample_rate;
4343 in->stream.common.get_buffer_size = in_get_buffer_size;
4344 in->stream.common.get_channels = in_get_channels;
4345 in->stream.common.get_format = in_get_format;
4346 in->stream.common.set_format = in_set_format;
4347 in->stream.common.standby = in_standby;
4348 in->stream.common.dump = in_dump;
4349 in->stream.common.set_parameters = in_set_parameters;
4350 in->stream.common.get_parameters = in_get_parameters;
4351 in->stream.common.add_audio_effect = in_add_audio_effect;
4352 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4353 in->stream.set_gain = in_set_gain;
4354 in->stream.read = in_read;
4355 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4356
4357 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004358 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 in->standby = 1;
4361 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004362 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004363 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364
4365 /* Update config params with the requested sample rate and channels */
4366 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004367 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4368 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4369 is_low_latency = true;
4370#if LOW_LATENCY_CAPTURE_USE_CASE
4371 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4372#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004373 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004374 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004375
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004376 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004377 if (in->realtime) {
4378 in->config = pcm_config_audio_capture_rt;
4379 in->sample_rate = in->config.rate;
4380 in->af_period_multiplier = af_period_multiplier;
4381 } else {
4382 in->config = pcm_config_audio_capture;
4383 in->config.rate = config->sample_rate;
4384 in->sample_rate = config->sample_rate;
4385 in->af_period_multiplier = 1;
4386 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304387 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004389 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304390 if (adev->mode != AUDIO_MODE_IN_CALL) {
4391 ret = -EINVAL;
4392 goto err_open;
4393 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004394 if (config->sample_rate == 0)
4395 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4396 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4397 config->sample_rate != 8000) {
4398 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4399 ret = -EINVAL;
4400 goto err_open;
4401 }
4402 if (config->format == AUDIO_FORMAT_DEFAULT)
4403 config->format = AUDIO_FORMAT_PCM_16_BIT;
4404 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4405 config->format = AUDIO_FORMAT_PCM_16_BIT;
4406 ret = -EINVAL;
4407 goto err_open;
4408 }
4409
4410 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4411 in->config = pcm_config_afe_proxy_record;
4412 in->config.channels = channel_count;
4413 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304414 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304415 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4416 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004417 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004418 audio_extn_compr_cap_format_supported(config->format) &&
4419 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004420 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004421 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304422 /* restrict 24 bit capture for unprocessed source only
4423 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4424 */
4425 if (config->format == AUDIO_FORMAT_DEFAULT) {
4426 config->format = AUDIO_FORMAT_PCM_16_BIT;
4427 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4428 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4429 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4430 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4431 bool ret_error = false;
4432 in->bit_width = 24;
4433 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4434 from HAL is 24_packed and 8_24
4435 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4436 24_packed return error indicating supported format is 24_packed
4437 *> In case of any other source requesting 24 bit or float return error
4438 indicating format supported is 16 bit only.
4439
4440 on error flinger will retry with supported format passed
4441 */
4442 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4443 (source != AUDIO_SOURCE_CAMCORDER)) {
4444 config->format = AUDIO_FORMAT_PCM_16_BIT;
4445 if( config->sample_rate > 48000)
4446 config->sample_rate = 48000;
4447 ret_error = true;
4448 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4449 in->config.format = PCM_FORMAT_S24_3LE;
4450 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4451 in->config.format = PCM_FORMAT_S24_LE;
4452 } else {
4453 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4454 ret_error = true;
4455 }
4456
4457 if (ret_error) {
4458 ret = -EINVAL;
4459 goto err_open;
4460 }
4461 }
4462
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004463 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004464 if (!in->realtime) {
4465 in->format = config->format;
4466 frame_size = audio_stream_in_frame_size(&in->stream);
4467 buffer_size = get_input_buffer_size(config->sample_rate,
4468 config->format,
4469 channel_count,
4470 is_low_latency);
4471 in->config.period_size = buffer_size / frame_size;
4472 }
4473
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004474 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4475 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4476 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004477 (in->config.rate == 8000 || in->config.rate == 16000 ||
4478 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004479 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4480 voice_extn_compress_voip_open_input_stream(in);
4481 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004484 /* This stream could be for sound trigger lab,
4485 get sound trigger pcm if present */
4486 audio_extn_sound_trigger_check_and_get_session(in);
4487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004489 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004490 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491
4492err_open:
4493 free(in);
4494 *stream_in = NULL;
4495 return ret;
4496}
4497
4498static void adev_close_input_stream(struct audio_hw_device *dev,
4499 struct audio_stream_in *stream)
4500{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004501 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004502 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004503 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304505 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004506
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304507 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004508 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304509
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004510 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304511 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004512 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304513 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004514 if (ret != 0)
4515 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4516 __func__, ret);
4517 } else
4518 in_standby(&stream->common);
4519
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004520 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004521 audio_extn_ssr_deinit();
4522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523
Mingming Yine62d7842013-10-25 16:26:03 -07004524 if(audio_extn_compr_cap_enabled() &&
4525 audio_extn_compr_cap_format_supported(in->config.format))
4526 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004527
Mingming Yinfd7607b2016-01-22 12:48:44 -08004528 if (in->is_st_session) {
4529 ALOGV("%s: sound trigger pcm stop lab", __func__);
4530 audio_extn_sound_trigger_stop_lab(in);
4531 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004532 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533 return;
4534}
4535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004536static int adev_dump(const audio_hw_device_t *device __unused,
4537 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538{
4539 return 0;
4540}
4541
4542static int adev_close(hw_device_t *device)
4543{
4544 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004545
4546 if (!adev)
4547 return 0;
4548
4549 pthread_mutex_lock(&adev_init_lock);
4550
4551 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004552 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004553 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004554 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004555 audio_route_free(adev->audio_route);
4556 free(adev->snd_dev_ref_cnt);
4557 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004558 if (adev->adm_deinit)
4559 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004560 free(device);
4561 adev = NULL;
4562 }
4563 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 return 0;
4566}
4567
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004568/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4569 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4570 * just that it _might_ work.
4571 */
4572static int period_size_is_plausible_for_low_latency(int period_size)
4573{
4574 switch (period_size) {
4575 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004576 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004577 case 240:
4578 case 320:
4579 case 480:
4580 return 1;
4581 default:
4582 return 0;
4583 }
4584}
4585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586static int adev_open(const hw_module_t *module, const char *name,
4587 hw_device_t **device)
4588{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004589 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4591
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004592 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004593 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004594 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004595 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004596 ALOGD("%s: returning existing instance of adev", __func__);
4597 ALOGD("%s: exit", __func__);
4598 pthread_mutex_unlock(&adev_init_lock);
4599 return 0;
4600 }
4601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 adev = calloc(1, sizeof(struct audio_device));
4603
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004604 if (!adev) {
4605 pthread_mutex_unlock(&adev_init_lock);
4606 return -ENOMEM;
4607 }
4608
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004609 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4612 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4613 adev->device.common.module = (struct hw_module_t *)module;
4614 adev->device.common.close = adev_close;
4615
4616 adev->device.init_check = adev_init_check;
4617 adev->device.set_voice_volume = adev_set_voice_volume;
4618 adev->device.set_master_volume = adev_set_master_volume;
4619 adev->device.get_master_volume = adev_get_master_volume;
4620 adev->device.set_master_mute = adev_set_master_mute;
4621 adev->device.get_master_mute = adev_get_master_mute;
4622 adev->device.set_mode = adev_set_mode;
4623 adev->device.set_mic_mute = adev_set_mic_mute;
4624 adev->device.get_mic_mute = adev_get_mic_mute;
4625 adev->device.set_parameters = adev_set_parameters;
4626 adev->device.get_parameters = adev_get_parameters;
4627 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4628 adev->device.open_output_stream = adev_open_output_stream;
4629 adev->device.close_output_stream = adev_close_output_stream;
4630 adev->device.open_input_stream = adev_open_input_stream;
4631 adev->device.close_input_stream = adev_close_input_stream;
4632 adev->device.dump = adev_dump;
4633
4634 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004636 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004637 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004640 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004641 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004642 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004643 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004644 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004645 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004646 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004647 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304648 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304649 adev->perf_lock_opts[0] = 0x101;
4650 adev->perf_lock_opts[1] = 0x20E;
4651 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304652
4653 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4654 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004656 adev->platform = platform_init(adev);
4657 if (!adev->platform) {
4658 free(adev->snd_dev_ref_cnt);
4659 free(adev);
4660 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4661 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004662 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004663 return -EINVAL;
4664 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004665
Naresh Tanniru4c630392014-05-12 01:05:52 +05304666 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4667
Eric Laurentc4aef752013-09-12 17:45:53 -07004668 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4669 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4670 if (adev->visualizer_lib == NULL) {
4671 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4672 } else {
4673 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4674 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004675 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004676 "visualizer_hal_start_output");
4677 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004678 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004679 "visualizer_hal_stop_output");
4680 }
4681 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004682 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004683 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004684
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004685 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4686 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4687 if (adev->offload_effects_lib == NULL) {
4688 ALOGE("%s: DLOPEN failed for %s", __func__,
4689 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4690 } else {
4691 ALOGV("%s: DLOPEN successful for %s", __func__,
4692 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4693 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304694 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004695 "offload_effects_bundle_hal_start_output");
4696 adev->offload_effects_stop_output =
4697 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4698 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004699 adev->offload_effects_set_hpx_state =
4700 (int (*)(bool))dlsym(adev->offload_effects_lib,
4701 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304702 adev->offload_effects_get_parameters =
4703 (void (*)(struct str_parms *, struct str_parms *))
4704 dlsym(adev->offload_effects_lib,
4705 "offload_effects_bundle_get_parameters");
4706 adev->offload_effects_set_parameters =
4707 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4708 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004709 }
4710 }
4711
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004712 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4713 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4714 if (adev->adm_lib == NULL) {
4715 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4716 } else {
4717 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4718 adev->adm_init = (adm_init_t)
4719 dlsym(adev->adm_lib, "adm_init");
4720 adev->adm_deinit = (adm_deinit_t)
4721 dlsym(adev->adm_lib, "adm_deinit");
4722 adev->adm_register_input_stream = (adm_register_input_stream_t)
4723 dlsym(adev->adm_lib, "adm_register_input_stream");
4724 adev->adm_register_output_stream = (adm_register_output_stream_t)
4725 dlsym(adev->adm_lib, "adm_register_output_stream");
4726 adev->adm_deregister_stream = (adm_deregister_stream_t)
4727 dlsym(adev->adm_lib, "adm_deregister_stream");
4728 adev->adm_request_focus = (adm_request_focus_t)
4729 dlsym(adev->adm_lib, "adm_request_focus");
4730 adev->adm_abandon_focus = (adm_abandon_focus_t)
4731 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004732 adev->adm_set_config = (adm_set_config_t)
4733 dlsym(adev->adm_lib, "adm_set_config");
4734 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4735 dlsym(adev->adm_lib, "adm_request_focus_v2");
4736 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4737 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4738 adev->adm_on_routing_change = (adm_on_routing_change_t)
4739 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004740 }
4741 }
4742
Mingming Yin514a8bc2014-07-29 15:22:21 -07004743 adev->bt_wb_speech_enabled = false;
4744
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004745 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746 *device = &adev->device.common;
4747
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004748 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4749 &adev->streams_output_cfg_list);
4750
Kiran Kandi910e1862013-10-29 13:29:42 -07004751 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004752
4753 char value[PROPERTY_VALUE_MAX];
4754 int trial;
4755 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4756 trial = atoi(value);
4757 if (period_size_is_plausible_for_low_latency(trial)) {
4758 pcm_config_low_latency.period_size = trial;
4759 pcm_config_low_latency.start_threshold = trial / 4;
4760 pcm_config_low_latency.avail_min = trial / 4;
4761 configured_low_latency_capture_period_size = trial;
4762 }
4763 }
4764 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4765 trial = atoi(value);
4766 if (period_size_is_plausible_for_low_latency(trial)) {
4767 configured_low_latency_capture_period_size = trial;
4768 }
4769 }
4770
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004771 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4772 af_period_multiplier = atoi(value);
4773 if (af_period_multiplier < 0)
4774 af_period_multiplier = 2;
4775 else if (af_period_multiplier > 4)
4776 af_period_multiplier = 4;
4777
4778 ALOGV("new period_multiplier = %d", af_period_multiplier);
4779 }
4780
vivek mehta446c3962015-09-14 10:57:35 -07004781 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004782 pthread_mutex_unlock(&adev_init_lock);
4783
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004784 if (adev->adm_init)
4785 adev->adm_data = adev->adm_init();
4786
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304787 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004788 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 return 0;
4790}
4791
4792static struct hw_module_methods_t hal_module_methods = {
4793 .open = adev_open,
4794};
4795
4796struct audio_module HAL_MODULE_INFO_SYM = {
4797 .common = {
4798 .tag = HARDWARE_MODULE_TAG,
4799 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4800 .hal_api_version = HARDWARE_HAL_API_VERSION,
4801 .id = AUDIO_HARDWARE_MODULE_ID,
4802 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004803 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804 .methods = &hal_module_methods,
4805 },
4806};