blob: 43c83de840d0f5dc936253e346f434f829b09943 [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
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800753 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
754 audio_extn_spkr_prot_is_enabled()) {
755 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700756 adev->snd_dev_ref_cnt[snd_device]--;
757 return -EINVAL;
758 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200759 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800760 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800761 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200762 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800763 return -EINVAL;
764 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530765 } else if (platform_can_split_snd_device(adev->platform, snd_device,
766 &num_devices, new_snd_devices)) {
767 for (i = 0; i < num_devices; i++) {
768 enable_snd_device(adev, new_snd_devices[i]);
769 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800770 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700771 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530772
773 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
774 (audio_extn_a2dp_start_playback() < 0)) {
775 ALOGE(" fail to configure A2dp control path ");
776 return -EINVAL;
777 }
778
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700779 /* due to the possibility of calibration overwrite between listen
780 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700781 audio_extn_sound_trigger_update_device_status(snd_device,
782 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530783 audio_extn_listen_update_device_status(snd_device,
784 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700785 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700786 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700787 audio_extn_sound_trigger_update_device_status(snd_device,
788 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530789 audio_extn_listen_update_device_status(snd_device,
790 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700791 return -EINVAL;
792 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300793 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700794 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530795
796 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
797 !adev->native_playback_enabled &&
798 audio_is_true_native_stream_active(adev)) {
799 ALOGD("%s: %d: napb: enabling native mode in hardware",
800 __func__, __LINE__);
801 audio_route_apply_and_update_path(adev->audio_route,
802 "true-native-mode");
803 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530804 } else
805 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 return 0;
808}
809
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700810int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700811 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530813 int i, num_devices = 0;
814 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700815 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
816
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800817 if (snd_device < SND_DEVICE_MIN ||
818 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800819 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800820 return -EINVAL;
821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
823 ALOGE("%s: device ref cnt is already 0", __func__);
824 return -EINVAL;
825 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700828
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700829 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
830 ALOGE("%s: Invalid sound device returned", __func__);
831 return -EINVAL;
832 }
833
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700835 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530836
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800837 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
838 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700839 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530840 } else if (platform_can_split_snd_device(adev->platform, snd_device,
841 &num_devices, new_snd_devices)) {
842 for (i = 0; i < num_devices; i++) {
843 disable_snd_device(adev, new_snd_devices[i]);
844 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300845 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700846 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300847 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700848
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530849 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
850 audio_extn_a2dp_stop_playback();
851
Ashish Jain81eb2a82015-05-13 10:52:34 +0530852 if (snd_device == SND_DEVICE_OUT_HDMI)
853 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530854 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
855 adev->native_playback_enabled) {
856 ALOGD("%s: %d: napb: disabling native mode in hardware",
857 __func__, __LINE__);
858 audio_route_reset_and_update_path(adev->audio_route,
859 "true-native-mode");
860 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530861 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
862 adev->asrc_mode_enabled) {
863 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
864 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
865 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530866 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530867
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200868 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700869 audio_extn_sound_trigger_update_device_status(snd_device,
870 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530871 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800872 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800875 return 0;
876}
877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530879 struct audio_usecase *uc_info,
880 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881{
882 struct listnode *node;
883 struct audio_usecase *usecase;
884 bool switch_device[AUDIO_USECASE_MAX];
885 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530886 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 /*
888 * This function is to make sure that all the usecases that are active on
889 * the hardware codec backend are always routed to any one device that is
890 * handled by the hardware codec.
891 * For example, if low-latency and deep-buffer usecases are currently active
892 * on speaker and out_set_parameters(headset) is received on low-latency
893 * output, then we have to make sure deep-buffer is also switched to headset,
894 * because of the limitation that both the devices cannot be enabled
895 * at the same time as they share the same backend.
896 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700897 /*
898 * This call is to check if we need to force routing for a particular stream
899 * If there is a backend configuration change for the device when a
900 * new stream starts, then ADM needs to be closed and re-opened with the new
901 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800902 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700903 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800904 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
905 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530906 /* For a2dp device reconfigure all active sessions
907 * with new AFE encoder format based on a2dp state
908 */
909 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
910 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
911 audio_extn_a2dp_is_force_device_switch()) {
912 force_routing = true;
913 force_restart_session = true;
914 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530915 ALOGD("%s:becf: force routing %d", __func__, force_routing);
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800918 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800919 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 for (i = 0; i < AUDIO_USECASE_MAX; i++)
921 switch_device[i] = false;
922
923 list_for_each(node, &adev->usecase_list) {
924 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800925
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530926 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
927 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530928 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530929 platform_get_snd_device_name(usecase->out_snd_device),
930 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800931 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530932 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530933 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530934 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
935 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
936 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530937 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
938 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
939 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530940 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
941 __func__, use_case_table[usecase->id],
942 platform_get_snd_device_name(usecase->out_snd_device));
943 disable_audio_route(adev, usecase);
944 switch_device[usecase->id] = true;
945 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 }
947 }
948
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530949 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
950 num_uc_to_switch);
951
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700953 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530955 /* Make sure the previous devices to be disabled first and then enable the
956 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700957 list_for_each(node, &adev->usecase_list) {
958 usecase = node_to_item(node, struct audio_usecase, list);
959 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700960 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 }
962 }
963
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700964 list_for_each(node, &adev->usecase_list) {
965 usecase = node_to_item(node, struct audio_usecase, list);
966 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700968 }
969 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530975 /* Update the out_snd_device only before enabling the audio route */
976 if (switch_device[usecase->id]) {
977 usecase->out_snd_device = snd_device;
978 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530979 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530980 use_case_table[usecase->id],
981 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530982 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530983 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700984 }
985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987}
988
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530989static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 struct audio_usecase *uc_info,
991 snd_device_t snd_device)
992{
993 struct listnode *node;
994 struct audio_usecase *usecase;
995 bool switch_device[AUDIO_USECASE_MAX];
996 int i, num_uc_to_switch = 0;
997
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530998 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
999 snd_device);
1000 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001001 /*
1002 * This function is to make sure that all the active capture usecases
1003 * are always routed to the same input sound device.
1004 * For example, if audio-record and voice-call usecases are currently
1005 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1006 * is received for voice call then we have to make sure that audio-record
1007 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1008 * because of the limitation that two devices cannot be enabled
1009 * at the same time if they share the same backend.
1010 */
1011 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1012 switch_device[i] = false;
1013
1014 list_for_each(node, &adev->usecase_list) {
1015 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001016 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001017 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301018 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001019 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301020 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001021 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001022 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001023 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1024 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001025 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001026 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001027 switch_device[usecase->id] = true;
1028 num_uc_to_switch++;
1029 }
1030 }
1031
1032 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001033 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301035 /* Make sure the previous devices to be disabled first and then enable the
1036 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001037 list_for_each(node, &adev->usecase_list) {
1038 usecase = node_to_item(node, struct audio_usecase, list);
1039 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001040 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001041 }
1042 }
1043
1044 list_for_each(node, &adev->usecase_list) {
1045 usecase = node_to_item(node, struct audio_usecase, list);
1046 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001047 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001048 }
1049 }
1050
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001051 /* Re-route all the usecases on the shared backend other than the
1052 specified usecase to new snd devices */
1053 list_for_each(node, &adev->usecase_list) {
1054 usecase = node_to_item(node, struct audio_usecase, list);
1055 /* Update the in_snd_device only before enabling the audio route */
1056 if (switch_device[usecase->id] ) {
1057 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001058 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301059 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 }
1061 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063}
1064
Mingming Yin3a941d42016-02-17 18:08:05 -08001065static void reset_hdmi_sink_caps(struct stream_out *out) {
1066 int i = 0;
1067
1068 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1069 out->supported_channel_masks[i] = 0;
1070 }
1071 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1072 out->supported_formats[i] = 0;
1073 }
1074 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1075 out->supported_sample_rates[i] = 0;
1076 }
1077}
1078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001080static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081{
Mingming Yin3a941d42016-02-17 18:08:05 -08001082 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001083 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084
Mingming Yin3a941d42016-02-17 18:08:05 -08001085 reset_hdmi_sink_caps(out);
1086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001089 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001090 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001091 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1092 case 6:
1093 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1094 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1095 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1096 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1097 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1098 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 break;
1100 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001101 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001102 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 break;
1104 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001105
1106 // check channel format caps
1107 i = 0;
1108 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1109 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1110 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1111 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1112 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1113 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1114 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1115 }
1116
1117 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1118 ALOGV(":%s HDMI supports DTS format", __func__);
1119 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1120 }
1121
1122 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1123 ALOGV(":%s HDMI supports DTS HD format", __func__);
1124 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1125 }
1126
1127
1128 // check sample rate caps
1129 i = 0;
1130 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1131 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1132 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1133 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1134 }
1135 }
1136
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001137 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138}
1139
Alexy Josephb1379942016-01-29 15:49:38 -08001140audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001141 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001142{
1143 struct audio_usecase *usecase;
1144 struct listnode *node;
1145
1146 list_for_each(node, &adev->usecase_list) {
1147 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001148 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001149 ALOGV("%s: usecase id %d", __func__, usecase->id);
1150 return usecase->id;
1151 }
1152 }
1153 return USECASE_INVALID;
1154}
1155
Alexy Josephb1379942016-01-29 15:49:38 -08001156struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001157 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158{
1159 struct audio_usecase *usecase;
1160 struct listnode *node;
1161
1162 list_for_each(node, &adev->usecase_list) {
1163 usecase = node_to_item(node, struct audio_usecase, list);
1164 if (usecase->id == uc_id)
1165 return usecase;
1166 }
1167 return NULL;
1168}
1169
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301170/*
1171 * is a true native playback active
1172 */
1173bool audio_is_true_native_stream_active(struct audio_device *adev)
1174{
1175 bool active = false;
1176 int i = 0;
1177 struct listnode *node;
1178
1179 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1180 ALOGV("%s:napb: not in true mode or non hdphones device",
1181 __func__);
1182 active = false;
1183 goto exit;
1184 }
1185
1186 list_for_each(node, &adev->usecase_list) {
1187 struct audio_usecase *uc;
1188 uc = node_to_item(node, struct audio_usecase, list);
1189 struct stream_out *curr_out =
1190 (struct stream_out*) uc->stream.out;
1191
1192 if (curr_out && PCM_PLAYBACK == uc->type) {
1193 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1194 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1195 uc->id, curr_out->sample_rate,
1196 curr_out->bit_width,
1197 platform_get_snd_device_name(uc->out_snd_device));
1198
1199 if (is_offload_usecase(uc->id) &&
1200 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1201 active = true;
1202 ALOGD("%s:napb:native stream detected", __func__);
1203 }
1204 }
1205 }
1206exit:
1207 return active;
1208}
1209
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301210/*
1211 * if native DSD playback active
1212 */
1213bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1214{
1215 bool active = false;
1216 struct listnode *node = NULL;
1217 struct audio_usecase *uc = NULL;
1218 struct stream_out *curr_out = NULL;
1219
1220 list_for_each(node, &adev->usecase_list) {
1221 uc = node_to_item(node, struct audio_usecase, list);
1222 curr_out = (struct stream_out*) uc->stream.out;
1223
1224 if (curr_out && PCM_PLAYBACK == uc->type &&
1225 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1226 active = true;
1227 ALOGV("%s:DSD playback is active", __func__);
1228 }
1229 }
1230 return active;
1231}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301232
1233static bool force_device_switch(struct audio_usecase *usecase)
1234{
1235 bool ret = false;
1236 bool is_it_true_mode = false;
1237
1238 if (is_offload_usecase(usecase->id) &&
1239 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001240 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1241 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1242 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301243 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1244 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1245 (!is_it_true_mode && adev->native_playback_enabled)){
1246 ret = true;
1247 ALOGD("napb: time to toggle native mode");
1248 }
1249 }
1250
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301251 // Force all a2dp output devices to reconfigure for proper AFE encode format
1252 if((usecase->stream.out) &&
1253 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1254 audio_extn_a2dp_is_force_device_switch()) {
1255 ALOGD("Force a2dp device switch to update new encoder config");
1256 ret = true;
1257 }
1258
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301259 return ret;
1260}
1261
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001262int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001264 snd_device_t out_snd_device = SND_DEVICE_NONE;
1265 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 struct audio_usecase *usecase = NULL;
1267 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001268 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001269 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001270 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001271 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301273 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1274
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 usecase = get_usecase_from_list(adev, uc_id);
1276 if (usecase == NULL) {
1277 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1278 return -EINVAL;
1279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001281 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001282 (usecase->type == VOIP_CALL) ||
1283 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001284 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001285 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001286 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 usecase->devices = usecase->stream.out->devices;
1288 } else {
1289 /*
1290 * If the voice call is active, use the sound devices of voice call usecase
1291 * so that it would not result any device switch. All the usecases will
1292 * be switched to new device when select_devices() is called for voice call
1293 * usecase. This is to avoid switching devices for voice call when
1294 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001295 * choose voice call device only if the use case device is
1296 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001298 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001299 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001300 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001301 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1302 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301303 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1304 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001305 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 in_snd_device = vc_usecase->in_snd_device;
1307 out_snd_device = vc_usecase->out_snd_device;
1308 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001309 } else if (voice_extn_compress_voip_is_active(adev)) {
1310 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001311 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001312 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1313 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001314 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001315 in_snd_device = voip_usecase->in_snd_device;
1316 out_snd_device = voip_usecase->out_snd_device;
1317 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001318 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001319 hfp_ucid = audio_extn_hfp_get_usecase();
1320 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001321 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001322 in_snd_device = hfp_usecase->in_snd_device;
1323 out_snd_device = hfp_usecase->out_snd_device;
1324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 }
1326 if (usecase->type == PCM_PLAYBACK) {
1327 usecase->devices = usecase->stream.out->devices;
1328 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001329 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001330 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001331 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (usecase->stream.out == adev->primary_output &&
1333 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001334 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001335 select_devices(adev, adev->active_input->usecase);
1336 }
1337 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 } else if (usecase->type == PCM_CAPTURE) {
1339 usecase->devices = usecase->stream.in->device;
1340 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001341 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001342 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001343 if (adev->active_input &&
1344 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301345 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1346 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1347 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001348 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001349 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001350 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1351 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001352 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001353 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001354 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001355 }
1356 }
1357
1358 if (out_snd_device == usecase->out_snd_device &&
1359 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301360
1361 if (!force_device_switch(usecase))
1362 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363 }
1364
sangwoobc677242013-08-08 16:53:43 +09001365 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001366 out_snd_device, platform_get_snd_device_name(out_snd_device),
1367 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 /*
1370 * Limitation: While in call, to do a device switch we need to disable
1371 * and enable both RX and TX devices though one of them is same as current
1372 * device.
1373 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001374 if ((usecase->type == VOICE_CALL) &&
1375 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1376 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001377 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001378 }
1379
1380 if (((usecase->type == VOICE_CALL) ||
1381 (usecase->type == VOIP_CALL)) &&
1382 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1383 /* Disable sidetone only if voice/voip call already exists */
1384 if (voice_is_call_state_active(adev) ||
1385 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001386 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001387 }
1388
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001389 /* Disable current sound devices */
1390 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001391 disable_audio_route(adev, usecase);
1392 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 }
1394
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001395 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001396 disable_audio_route(adev, usecase);
1397 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001398 }
1399
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001400 /* Applicable only on the targets that has external modem.
1401 * New device information should be sent to modem before enabling
1402 * the devices to reduce in-call device switch time.
1403 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001404 if ((usecase->type == VOICE_CALL) &&
1405 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1406 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001407 status = platform_switch_voice_call_enable_device_config(adev->platform,
1408 out_snd_device,
1409 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001410 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001411
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412 /* Enable new sound devices */
1413 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001414 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001415 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 }
1417
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001418 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301419 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001420 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001421 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001422
Avinash Vaish71a8b972014-07-24 15:36:33 +05301423 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001424 status = platform_switch_voice_call_device_post(adev->platform,
1425 out_snd_device,
1426 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301427 enable_audio_route_for_voice_usecases(adev, usecase);
1428 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001429
sangwoo170731f2013-06-08 15:36:36 +09001430 usecase->in_snd_device = in_snd_device;
1431 usecase->out_snd_device = out_snd_device;
1432
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301433 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001434 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301435 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001436 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301437 usecase->stream.out->flags,
1438 usecase->stream.out->format,
1439 usecase->stream.out->sample_rate,
1440 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301441 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301442 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001443 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301444 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001445
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001446 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001447
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001448 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1449 /* Enable sidetone only if other voice/voip call already exists */
1450 if (voice_is_call_state_active(adev) ||
1451 voice_extn_compress_voip_is_started(adev))
1452 voice_set_sidetone(adev, out_snd_device, true);
1453 }
1454
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001455 /* Applicable only on the targets that has external modem.
1456 * Enable device command should be sent to modem only after
1457 * enabling voice call mixer controls
1458 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001459 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001460 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1461 out_snd_device,
1462 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301463 ALOGD("%s: done",__func__);
1464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 return status;
1466}
1467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468static int stop_input_stream(struct stream_in *in)
1469{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301470 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471 struct audio_usecase *uc_info;
1472 struct audio_device *adev = in->dev;
1473
Eric Laurentc8400632013-02-14 19:04:54 -08001474 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475
Eric Laurent994a6932013-07-17 11:51:42 -07001476 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 uc_info = get_usecase_from_list(adev, in->usecase);
1479 if (uc_info == NULL) {
1480 ALOGE("%s: Could not find the usecase (%d) in the list",
1481 __func__, in->usecase);
1482 return -EINVAL;
1483 }
1484
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001485 /* Close in-call recording streams */
1486 voice_check_and_stop_incall_rec_usecase(adev, in);
1487
Eric Laurent150dbfe2013-02-27 14:31:02 -08001488 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001489 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001490
1491 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001492 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001494 list_remove(&uc_info->list);
1495 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Eric Laurent994a6932013-07-17 11:51:42 -07001497 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 return ret;
1499}
1500
1501int start_input_stream(struct stream_in *in)
1502{
1503 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001504 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 struct audio_usecase *uc_info;
1506 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301507 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Mingming Yin2664a5b2015-09-03 10:53:11 -07001509 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1510 if (get_usecase_from_list(adev, usecase) == NULL)
1511 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301512 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1513 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001514
Naresh Tanniru80659832014-06-04 18:17:56 +05301515
1516 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301517 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301518 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301519 goto error_config;
1520 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301521
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001522 /* Check if source matches incall recording usecase criteria */
1523 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1524 if (ret)
1525 goto error_config;
1526 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001527 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1528
1529 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1530 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1531 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001532 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001533 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001534
Eric Laurentb23d5282013-05-14 15:27:20 -07001535 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 if (in->pcm_device_id < 0) {
1537 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1538 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001539 ret = -EINVAL;
1540 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542
1543 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001545
1546 if (!uc_info) {
1547 ret = -ENOMEM;
1548 goto error_config;
1549 }
1550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551 uc_info->id = in->usecase;
1552 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001553 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 uc_info->devices = in->device;
1555 uc_info->in_snd_device = SND_DEVICE_NONE;
1556 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001558 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301559 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1560 adev->perf_lock_opts,
1561 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301564 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1565 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001566
1567 unsigned int flags = PCM_IN;
1568 unsigned int pcm_open_retry_count = 0;
1569
1570 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1571 flags |= PCM_MMAP | PCM_NOIRQ;
1572 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001573 } else if (in->realtime) {
1574 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001575 }
1576
1577 while (1) {
1578 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1579 flags, &in->config);
1580 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1581 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1582 if (in->pcm != NULL) {
1583 pcm_close(in->pcm);
1584 in->pcm = NULL;
1585 }
1586 if (pcm_open_retry_count-- == 0) {
1587 ret = -EIO;
1588 goto error_open;
1589 }
1590 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1591 continue;
1592 }
1593 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001594 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001595
1596 ALOGV("%s: pcm_prepare", __func__);
1597 ret = pcm_prepare(in->pcm);
1598 if (ret < 0) {
1599 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1600 pcm_close(in->pcm);
1601 in->pcm = NULL;
1602 goto error_open;
1603 }
1604
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001605 register_in_stream(in);
1606 if (in->realtime) {
1607 ret = pcm_start(in->pcm);
1608 if (ret < 0)
1609 goto error_open;
1610 }
1611
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301612 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001613 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001614
Eric Laurentc8400632013-02-14 19:04:54 -08001615 return ret;
1616
1617error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301618 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001620error_config:
1621 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301622 /*
1623 * sleep 50ms to allow sufficient time for kernel
1624 * drivers to recover incases like SSR.
1625 */
1626 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001627 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001628
1629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630}
1631
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001632void lock_input_stream(struct stream_in *in)
1633{
1634 pthread_mutex_lock(&in->pre_lock);
1635 pthread_mutex_lock(&in->lock);
1636 pthread_mutex_unlock(&in->pre_lock);
1637}
1638
1639void lock_output_stream(struct stream_out *out)
1640{
1641 pthread_mutex_lock(&out->pre_lock);
1642 pthread_mutex_lock(&out->lock);
1643 pthread_mutex_unlock(&out->pre_lock);
1644}
1645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646/* must be called with out->lock locked */
1647static int send_offload_cmd_l(struct stream_out* out, int command)
1648{
1649 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1650
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001651 if (!cmd) {
1652 ALOGE("failed to allocate mem for command 0x%x", command);
1653 return -ENOMEM;
1654 }
1655
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001656 ALOGVV("%s %d", __func__, command);
1657
1658 cmd->cmd = command;
1659 list_add_tail(&out->offload_cmd_list, &cmd->node);
1660 pthread_cond_signal(&out->offload_cond);
1661 return 0;
1662}
1663
1664/* must be called iwth out->lock locked */
1665static void stop_compressed_output_l(struct stream_out *out)
1666{
1667 out->offload_state = OFFLOAD_STATE_IDLE;
1668 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001669 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 if (out->compr != NULL) {
1671 compress_stop(out->compr);
1672 while (out->offload_thread_blocked) {
1673 pthread_cond_wait(&out->cond, &out->lock);
1674 }
1675 }
1676}
1677
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001678bool is_offload_usecase(audio_usecase_t uc_id)
1679{
1680 unsigned int i;
1681 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1682 if (uc_id == offload_usecases[i])
1683 return true;
1684 }
1685 return false;
1686}
1687
vivek mehta446c3962015-09-14 10:57:35 -07001688static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001689{
vivek mehta446c3962015-09-14 10:57:35 -07001690 audio_usecase_t ret_uc = USECASE_INVALID;
1691 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001692 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001693 if (!adev->multi_offload_enable) {
1694 if (is_direct_pcm)
1695 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1696 else
1697 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001698
vivek mehta446c3962015-09-14 10:57:35 -07001699 pthread_mutex_lock(&adev->lock);
1700 if (get_usecase_from_list(adev, ret_uc) != NULL)
1701 ret_uc = USECASE_INVALID;
1702 pthread_mutex_unlock(&adev->lock);
1703
1704 return ret_uc;
1705 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001706
1707 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001708 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1709 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1710 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1711 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001712 break;
1713 }
1714 }
vivek mehta446c3962015-09-14 10:57:35 -07001715
1716 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1717 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001718}
1719
1720static void free_offload_usecase(struct audio_device *adev,
1721 audio_usecase_t uc_id)
1722{
vivek mehta446c3962015-09-14 10:57:35 -07001723 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001724 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001725
1726 if (!adev->multi_offload_enable)
1727 return;
1728
1729 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1730 if (offload_usecases[offload_uc_index] == uc_id) {
1731 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001732 break;
1733 }
1734 }
1735 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1736}
1737
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738static void *offload_thread_loop(void *context)
1739{
1740 struct stream_out *out = (struct stream_out *) context;
1741 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001742 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001743
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1745 set_sched_policy(0, SP_FOREGROUND);
1746 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1747
1748 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001749 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 for (;;) {
1751 struct offload_cmd *cmd = NULL;
1752 stream_callback_event_t event;
1753 bool send_callback = false;
1754
1755 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1756 __func__, list_empty(&out->offload_cmd_list),
1757 out->offload_state);
1758 if (list_empty(&out->offload_cmd_list)) {
1759 ALOGV("%s SLEEPING", __func__);
1760 pthread_cond_wait(&out->offload_cond, &out->lock);
1761 ALOGV("%s RUNNING", __func__);
1762 continue;
1763 }
1764
1765 item = list_head(&out->offload_cmd_list);
1766 cmd = node_to_item(item, struct offload_cmd, node);
1767 list_remove(item);
1768
1769 ALOGVV("%s STATE %d CMD %d out->compr %p",
1770 __func__, out->offload_state, cmd->cmd, out->compr);
1771
1772 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1773 free(cmd);
1774 break;
1775 }
1776
1777 if (out->compr == NULL) {
1778 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001779 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 pthread_cond_signal(&out->cond);
1781 continue;
1782 }
1783 out->offload_thread_blocked = true;
1784 pthread_mutex_unlock(&out->lock);
1785 send_callback = false;
1786 switch(cmd->cmd) {
1787 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001788 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001790 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 send_callback = true;
1792 event = STREAM_CBK_EVENT_WRITE_READY;
1793 break;
1794 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001795 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301796 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001797 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301798 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001799 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301800 if (ret < 0)
1801 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301802 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301803 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001804 compress_drain(out->compr);
1805 else
1806 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301807 if (ret != -ENETRESET) {
1808 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301809 pthread_mutex_lock(&out->lock);
1810 out->send_new_metadata = 1;
1811 out->send_next_track_params = true;
1812 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301813 event = STREAM_CBK_EVENT_DRAIN_READY;
1814 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1815 } else
1816 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 break;
1818 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001819 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001820 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001821 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 send_callback = true;
1823 event = STREAM_CBK_EVENT_DRAIN_READY;
1824 break;
1825 default:
1826 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1827 break;
1828 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001829 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001830 out->offload_thread_blocked = false;
1831 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001832 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001833 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001835 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 free(cmd);
1837 }
1838
1839 pthread_cond_signal(&out->cond);
1840 while (!list_empty(&out->offload_cmd_list)) {
1841 item = list_head(&out->offload_cmd_list);
1842 list_remove(item);
1843 free(node_to_item(item, struct offload_cmd, node));
1844 }
1845 pthread_mutex_unlock(&out->lock);
1846
1847 return NULL;
1848}
1849
1850static int create_offload_callback_thread(struct stream_out *out)
1851{
1852 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1853 list_init(&out->offload_cmd_list);
1854 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1855 offload_thread_loop, out);
1856 return 0;
1857}
1858
1859static int destroy_offload_callback_thread(struct stream_out *out)
1860{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001861 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001862 stop_compressed_output_l(out);
1863 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1864
1865 pthread_mutex_unlock(&out->lock);
1866 pthread_join(out->offload_thread, (void **) NULL);
1867 pthread_cond_destroy(&out->offload_cond);
1868
1869 return 0;
1870}
1871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872static int stop_output_stream(struct stream_out *out)
1873{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301874 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 struct audio_usecase *uc_info;
1876 struct audio_device *adev = out->dev;
1877
Eric Laurent994a6932013-07-17 11:51:42 -07001878 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 uc_info = get_usecase_from_list(adev, out->usecase);
1881 if (uc_info == NULL) {
1882 ALOGE("%s: Could not find the usecase (%d) in the list",
1883 __func__, out->usecase);
1884 return -EINVAL;
1885 }
1886
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001887 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301888 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001889 if (adev->visualizer_stop_output != NULL)
1890 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001891
1892 audio_extn_dts_remove_state_notifier_node(out->usecase);
1893
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001894 if (adev->offload_effects_stop_output != NULL)
1895 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1896 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001897
Eric Laurent150dbfe2013-02-27 14:31:02 -08001898 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001899 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900
1901 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001902 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001904 list_remove(&uc_info->list);
1905 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001907 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301908 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001909 ALOGV("Disable passthrough , reset mixer to pcm");
1910 /* NO_PASSTHROUGH */
1911 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001912 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001913 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1914 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001915
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301916 /* Must be called after removing the usecase from list */
1917 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301918 audio_extn_keep_alive_start();
1919
Eric Laurent994a6932013-07-17 11:51:42 -07001920 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 return ret;
1922}
1923
1924int start_output_stream(struct stream_out *out)
1925{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 struct audio_usecase *uc_info;
1928 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301929 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001931 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1932 ret = -EINVAL;
1933 goto error_config;
1934 }
1935
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301936 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1937 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1938 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301939
Naresh Tanniru80659832014-06-04 18:17:56 +05301940 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301941 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301942 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301943 goto error_config;
1944 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301945
Eric Laurentb23d5282013-05-14 15:27:20 -07001946 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 if (out->pcm_device_id < 0) {
1948 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1949 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001950 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001951 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952 }
1953
1954 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001955
1956 if (!uc_info) {
1957 ret = -ENOMEM;
1958 goto error_config;
1959 }
1960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 uc_info->id = out->usecase;
1962 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 uc_info->devices = out->devices;
1965 uc_info->in_snd_device = SND_DEVICE_NONE;
1966 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001967 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301969 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1970 adev->perf_lock_opts,
1971 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301972
1973 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1974 audio_extn_keep_alive_stop();
1975 if (audio_extn_passthru_is_enabled() &&
1976 audio_extn_passthru_is_passthrough_stream(out)) {
1977 audio_extn_passthru_on_start(out);
1978 audio_extn_passthru_update_stream_configuration(adev, out);
1979 }
1980 }
1981
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001982 select_devices(adev, out->usecase);
1983
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001984 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1985 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001986 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001987 unsigned int flags = PCM_OUT;
1988 unsigned int pcm_open_retry_count = 0;
1989 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1990 flags |= PCM_MMAP | PCM_NOIRQ;
1991 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001992 } else if (out->realtime) {
1993 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001994 } else
1995 flags |= PCM_MONOTONIC;
1996
1997 while (1) {
1998 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1999 flags, &out->config);
2000 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2001 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2002 if (out->pcm != NULL) {
2003 pcm_close(out->pcm);
2004 out->pcm = NULL;
2005 }
2006 if (pcm_open_retry_count-- == 0) {
2007 ret = -EIO;
2008 goto error_open;
2009 }
2010 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2011 continue;
2012 }
2013 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002015
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002016 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2017 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002018
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002019 ALOGV("%s: pcm_prepare", __func__);
2020 if (pcm_is_ready(out->pcm)) {
2021 ret = pcm_prepare(out->pcm);
2022 if (ret < 0) {
2023 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2024 pcm_close(out->pcm);
2025 out->pcm = NULL;
2026 goto error_open;
2027 }
2028 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002030 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2031 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002033 out->compr = compress_open(adev->snd_card,
2034 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 COMPRESS_IN, &out->compr_config);
2036 if (out->compr && !is_compress_ready(out->compr)) {
2037 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2038 compress_close(out->compr);
2039 out->compr = NULL;
2040 ret = -EIO;
2041 goto error_open;
2042 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302043 /* compress_open sends params of the track, so reset the flag here */
2044 out->is_compr_metadata_avail = false;
2045
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002046 if (out->offload_callback)
2047 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002048
Fred Oh3f43e742015-03-04 18:42:34 -08002049 /* Since small bufs uses blocking writes, a write will be blocked
2050 for the default max poll time (20s) in the event of an SSR.
2051 Reduce the poll time to observe and deal with SSR faster.
2052 */
Ashish Jain5106d362016-05-11 19:23:33 +05302053 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002054 compress_set_max_poll_wait(out->compr, 1000);
2055 }
2056
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002057 audio_extn_dts_create_state_notifier_node(out->usecase);
2058 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2059 popcount(out->channel_mask),
2060 out->playback_started);
2061
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002062#ifdef DS1_DOLBY_DDP_ENABLED
2063 if (audio_extn_is_dolby_format(out->format))
2064 audio_extn_dolby_send_ddp_endp_params(adev);
2065#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302066 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002067 if (adev->visualizer_start_output != NULL)
2068 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2069 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302070 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002071 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002072 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002074
2075 if (ret == 0) {
2076 register_out_stream(out);
2077 if (out->realtime) {
2078 ret = pcm_start(out->pcm);
2079 if (ret < 0)
2080 goto error_open;
2081 }
2082 }
2083
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302084 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002085 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002086
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002087 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302089 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002091error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302092 /*
2093 * sleep 50ms to allow sufficient time for kernel
2094 * drivers to recover incases like SSR.
2095 */
2096 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002097 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098}
2099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100static int check_input_parameters(uint32_t sample_rate,
2101 audio_format_t format,
2102 int channel_count)
2103{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002104 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302106 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2107 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2108 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002109 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302110 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002111
2112 switch (channel_count) {
2113 case 1:
2114 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302115 case 3:
2116 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002117 case 6:
2118 break;
2119 default:
2120 ret = -EINVAL;
2121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122
2123 switch (sample_rate) {
2124 case 8000:
2125 case 11025:
2126 case 12000:
2127 case 16000:
2128 case 22050:
2129 case 24000:
2130 case 32000:
2131 case 44100:
2132 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302133 case 96000:
2134 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 break;
2136 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002137 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 }
2139
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002140 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141}
2142
2143static size_t get_input_buffer_size(uint32_t sample_rate,
2144 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002145 int channel_count,
2146 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147{
2148 size_t size = 0;
2149
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002150 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2151 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002153 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002154 if (is_low_latency)
2155 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302156
2157 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002159 /* make sure the size is multiple of 32 bytes
2160 * At 48 kHz mono 16-bit PCM:
2161 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2162 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2163 */
2164 size += 0x1f;
2165 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002166
2167 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168}
2169
Ashish Jain5106d362016-05-11 19:23:33 +05302170static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2171{
2172 uint64_t actual_frames_rendered = 0;
2173 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2174
2175 /* This adjustment accounts for buffering after app processor.
2176 * It is based on estimated DSP latency per use case, rather than exact.
2177 */
2178 int64_t platform_latency = platform_render_latency(out->usecase) *
2179 out->sample_rate / 1000000LL;
2180
2181 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2182 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2183 * hence only estimate.
2184 */
2185 int64_t signed_frames = out->written - kernel_buffer_size;
2186
2187 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2188
2189 if (signed_frames > 0)
2190 actual_frames_rendered = signed_frames;
2191
2192 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2193 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2194 (long long int)out->written, (int)kernel_buffer_size,
2195 audio_bytes_per_sample(out->compr_config.codec->format),
2196 popcount(out->channel_mask));
2197
2198 return actual_frames_rendered;
2199}
2200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2202{
2203 struct stream_out *out = (struct stream_out *)stream;
2204
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206}
2207
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002208static int out_set_sample_rate(struct audio_stream *stream __unused,
2209 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210{
2211 return -ENOSYS;
2212}
2213
2214static size_t out_get_buffer_size(const struct audio_stream *stream)
2215{
2216 struct stream_out *out = (struct stream_out *)stream;
2217
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002218 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002220 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2221 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302222 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302223 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002225 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002226 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227}
2228
2229static uint32_t out_get_channels(const struct audio_stream *stream)
2230{
2231 struct stream_out *out = (struct stream_out *)stream;
2232
2233 return out->channel_mask;
2234}
2235
2236static audio_format_t out_get_format(const struct audio_stream *stream)
2237{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 struct stream_out *out = (struct stream_out *)stream;
2239
2240 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241}
2242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002243static int out_set_format(struct audio_stream *stream __unused,
2244 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245{
2246 return -ENOSYS;
2247}
2248
2249static int out_standby(struct audio_stream *stream)
2250{
2251 struct stream_out *out = (struct stream_out *)stream;
2252 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302254 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2255 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002257 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002259 if (adev->adm_deregister_stream)
2260 adev->adm_deregister_stream(adev->adm_data, out->handle);
2261
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002262 if (is_offload_usecase(out->usecase))
2263 stop_compressed_output_l(out);
2264
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002265 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002267 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2268 voice_extn_compress_voip_close_output_stream(stream);
2269 pthread_mutex_unlock(&adev->lock);
2270 pthread_mutex_unlock(&out->lock);
2271 ALOGD("VOIP output entered standby");
2272 return 0;
2273 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274 if (out->pcm) {
2275 pcm_close(out->pcm);
2276 out->pcm = NULL;
2277 }
2278 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002279 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302280 out->send_next_track_params = false;
2281 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002282 out->gapless_mdata.encoder_delay = 0;
2283 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 if (out->compr != NULL) {
2285 compress_close(out->compr);
2286 out->compr = NULL;
2287 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002290 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 }
2292 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302293 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 return 0;
2295}
2296
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002297static int out_dump(const struct audio_stream *stream __unused,
2298 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299{
2300 return 0;
2301}
2302
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002303static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2304{
2305 int ret = 0;
2306 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002307
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002308 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002309 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002310 return -EINVAL;
2311 }
2312
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302313 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002314
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002315 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2316 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302317 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002318 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002319 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2320 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302321 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002322 }
2323
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002324 ALOGV("%s new encoder delay %u and padding %u", __func__,
2325 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2326
2327 return 0;
2328}
2329
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002330static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2331{
2332 return out == adev->primary_output || out == adev->voice_tx_output;
2333}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2336{
2337 struct stream_out *out = (struct stream_out *)stream;
2338 struct audio_device *adev = out->dev;
2339 struct str_parms *parms;
2340 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002341 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342
sangwoobc677242013-08-08 16:53:43 +09002343 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002344 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302346 if (!parms)
2347 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002348 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2349 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002351 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002352 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002354 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002355 * When HDMI cable is unplugged the music playback is paused and
2356 * the policy manager sends routing=0. But the audioflinger continues
2357 * to write data until standby time (3sec). As the HDMI core is
2358 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002359 * Avoid this by routing audio to speaker until standby.
2360 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002361 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2362 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302363 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002364 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2365 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002366 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302367 /*
2368 * When A2DP is disconnected the
2369 * music playback is paused and the policy manager sends routing=0
2370 * But the audioflingercontinues to write data until standby time
2371 * (3sec). As BT is turned off, the write gets blocked.
2372 * Avoid this by routing audio to speaker until standby.
2373 */
2374 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2375 (val == AUDIO_DEVICE_NONE)) {
2376 val = AUDIO_DEVICE_OUT_SPEAKER;
2377 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002378
2379 /*
2380 * select_devices() call below switches all the usecases on the same
2381 * backend to the new device. Refer to check_usecases_codec_backend() in
2382 * the select_devices(). But how do we undo this?
2383 *
2384 * For example, music playback is active on headset (deep-buffer usecase)
2385 * and if we go to ringtones and select a ringtone, low-latency usecase
2386 * will be started on headset+speaker. As we can't enable headset+speaker
2387 * and headset devices at the same time, select_devices() switches the music
2388 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2389 * So when the ringtone playback is completed, how do we undo the same?
2390 *
2391 * We are relying on the out_set_parameters() call on deep-buffer output,
2392 * once the ringtone playback is ended.
2393 * NOTE: We should not check if the current devices are same as new devices.
2394 * Because select_devices() must be called to switch back the music
2395 * playback to headset.
2396 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002397 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002398 audio_devices_t new_dev = val;
2399 bool same_dev = out->devices == new_dev;
2400 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002401
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002402 if (output_drives_call(adev, out)) {
2403 if(!voice_is_in_call(adev)) {
2404 if (adev->mode == AUDIO_MODE_IN_CALL) {
2405 adev->current_call_output = out;
2406 ret = voice_start_call(adev);
2407 }
2408 } else {
2409 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002410 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002411 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002412 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002413
2414 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002415 if (!same_dev) {
2416 ALOGV("update routing change");
2417 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302418 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2419 adev->perf_lock_opts,
2420 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002421 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002422 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302423 if (!same_dev)
2424 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002425 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002426 }
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002429 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002431
2432 if (out == adev->primary_output) {
2433 pthread_mutex_lock(&adev->lock);
2434 audio_extn_set_parameters(adev, parms);
2435 pthread_mutex_unlock(&adev->lock);
2436 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002437 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002438 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002439 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002440
2441 audio_extn_dts_create_state_notifier_node(out->usecase);
2442 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2443 popcount(out->channel_mask),
2444 out->playback_started);
2445
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002446 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002447 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302450error:
Eric Laurent994a6932013-07-17 11:51:42 -07002451 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 return ret;
2453}
2454
2455static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2456{
2457 struct stream_out *out = (struct stream_out *)stream;
2458 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002459 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 char value[256];
2461 struct str_parms *reply = str_parms_create();
2462 size_t i, j;
2463 int ret;
2464 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002465
2466 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002467 if (reply) {
2468 str_parms_destroy(reply);
2469 }
2470 if (query) {
2471 str_parms_destroy(query);
2472 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002473 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2474 return NULL;
2475 }
2476
Eric Laurent994a6932013-07-17 11:51:42 -07002477 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2479 if (ret >= 0) {
2480 value[0] = '\0';
2481 i = 0;
2482 while (out->supported_channel_masks[i] != 0) {
2483 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2484 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2485 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002486 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002488 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 first = false;
2490 break;
2491 }
2492 }
2493 i++;
2494 }
2495 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2496 str = str_parms_to_str(reply);
2497 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002498 voice_extn_out_get_parameters(out, query, reply);
2499 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002500 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002501 free(str);
2502 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002505
Alexy Joseph62142aa2015-11-16 15:10:34 -08002506
2507 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2508 if (ret >= 0) {
2509 value[0] = '\0';
2510 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2511 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302512 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002513 } else {
2514 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302515 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002516 }
2517 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002518 if (str)
2519 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002520 str = str_parms_to_str(reply);
2521 }
2522
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002523 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2524 if (ret >= 0) {
2525 value[0] = '\0';
2526 i = 0;
2527 first = true;
2528 while (out->supported_formats[i] != 0) {
2529 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2530 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2531 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002532 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002533 }
2534 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2535 first = false;
2536 break;
2537 }
2538 }
2539 i++;
2540 }
2541 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002542 if (str)
2543 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002544 str = str_parms_to_str(reply);
2545 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002546
2547 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2548 if (ret >= 0) {
2549 value[0] = '\0';
2550 i = 0;
2551 first = true;
2552 while (out->supported_sample_rates[i] != 0) {
2553 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2554 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2555 if (!first) {
2556 strlcat(value, "|", sizeof(value));
2557 }
2558 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2559 first = false;
2560 break;
2561 }
2562 }
2563 i++;
2564 }
2565 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2566 if (str)
2567 free(str);
2568 str = str_parms_to_str(reply);
2569 }
2570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 str_parms_destroy(query);
2572 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002573 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 return str;
2575}
2576
2577static uint32_t out_get_latency(const struct audio_stream_out *stream)
2578{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002579 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002581 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Alexy Josephaa54c872014-12-03 02:46:47 -08002583 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002584 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002585 } else if (out->realtime) {
2586 // since the buffer won't be filled up faster than realtime,
2587 // return a smaller number
2588 if (out->config.rate)
2589 period_ms = (out->af_period_multiplier * out->config.period_size *
2590 1000) / (out->config.rate);
2591 else
2592 period_ms = 0;
2593 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002594 } else {
2595 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002597 }
2598
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302599 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002600 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601}
2602
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302603static float AmpToDb(float amplification)
2604{
2605 if (amplification == 0) {
2606 return DSD_VOLUME_MIN_DB;
2607 }
2608 return 20 * log10(amplification);
2609}
2610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611static int out_set_volume(struct audio_stream_out *stream, float left,
2612 float right)
2613{
Eric Laurenta9024de2013-04-04 09:19:12 -07002614 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002615 int volume[2];
2616
Eric Laurenta9024de2013-04-04 09:19:12 -07002617 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2618 /* only take left channel into account: the API is for stereo anyway */
2619 out->muted = (left == 0.0f);
2620 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002621 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302622 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002623 /*
2624 * Set mute or umute on HDMI passthrough stream.
2625 * Only take left channel into account.
2626 * Mute is 0 and unmute 1
2627 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302628 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302629 } else if (out->format == AUDIO_FORMAT_DSD){
2630 char mixer_ctl_name[128] = "DSD Volume";
2631 struct audio_device *adev = out->dev;
2632 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2633
2634 if (!ctl) {
2635 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2636 __func__, mixer_ctl_name);
2637 return -EINVAL;
2638 }
2639 volume[0] = (int)(AmpToDb(left));
2640 volume[1] = (int)(AmpToDb(right));
2641 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2642 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002643 } else {
2644 char mixer_ctl_name[128];
2645 struct audio_device *adev = out->dev;
2646 struct mixer_ctl *ctl;
2647 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002648 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002650 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2651 "Compress Playback %d Volume", pcm_device_id);
2652 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2653 if (!ctl) {
2654 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2655 __func__, mixer_ctl_name);
2656 return -EINVAL;
2657 }
2658 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2659 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2660 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2661 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 return -ENOSYS;
2666}
2667
2668static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2669 size_t bytes)
2670{
2671 struct stream_out *out = (struct stream_out *)stream;
2672 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302673 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002674 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002676 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302677
Naresh Tanniru80659832014-06-04 18:17:56 +05302678 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002679
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302680 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302681 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302682 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2683 pthread_mutex_unlock(&out->lock);
2684 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302685 } else {
2686 /* increase written size during SSR to avoid mismatch
2687 * with the written frames count in AF
2688 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002689 // bytes per frame
2690 size_t bpf = audio_bytes_per_sample(out->format) *
2691 audio_channel_count_from_out_mask(out->channel_mask);
2692 if (bpf != 0)
2693 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302694 ALOGD(" %s: sound card is not active/SSR state", __func__);
2695 ret= -EIO;
2696 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302697 }
2698 }
2699
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302700 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302701 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2702 if (audio_bytes_per_sample(out->format) != 0)
2703 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2704 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302705 goto exit;
2706 }
2707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002709 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002710 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002711 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2712 ret = voice_extn_compress_voip_start_output_stream(out);
2713 else
2714 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002715 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002716 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002718 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 goto exit;
2720 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002721
2722 if (last_known_cal_step != -1) {
2723 ALOGD("%s: retry previous failed cal level set", __func__);
2724 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2725 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727
Ashish Jain81eb2a82015-05-13 10:52:34 +05302728 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002729 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302730 adev->is_channel_status_set = true;
2731 }
2732
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002733 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002734 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002735 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002736 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002737 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2738 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302739 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2740 ALOGD("copl(%p):send next track params in gapless", out);
2741 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2742 out->send_next_track_params = false;
2743 out->is_compr_metadata_avail = false;
2744 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002745 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302746 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302747 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002748
Ashish Jain83a6cc22016-06-28 14:34:17 +05302749 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302750 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302751 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302752 pthread_mutex_unlock(&out->lock);
2753 return -EINVAL;
2754 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302755 audio_format_t dst_format = out->hal_op_format;
2756 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302757
2758 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2759 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2760
Ashish Jain83a6cc22016-06-28 14:34:17 +05302761 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302762 dst_format,
2763 buffer,
2764 src_format,
2765 frames);
2766
Ashish Jain83a6cc22016-06-28 14:34:17 +05302767 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302768 bytes_to_write);
2769
2770 /*Convert written bytes in audio flinger format*/
2771 if (ret > 0)
2772 ret = ((ret * format_to_bitwidth_table[out->format]) /
2773 format_to_bitwidth_table[dst_format]);
2774 }
2775 } else
2776 ret = compress_write(out->compr, buffer, bytes);
2777
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302778 if (ret < 0)
2779 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302780 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002781 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302782 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302784 } else if (-ENETRESET == ret) {
2785 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2786 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2787 pthread_mutex_unlock(&out->lock);
2788 out_standby(&out->stream.common);
2789 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002790 }
Ashish Jain5106d362016-05-11 19:23:33 +05302791 if ( ret == (ssize_t)bytes && !out->non_blocking)
2792 out->written += bytes;
2793
Naresh Tanniru80659832014-06-04 18:17:56 +05302794 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002795 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002796 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002797 out->playback_started = 1;
2798 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002799
2800 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2801 popcount(out->channel_mask),
2802 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 }
2804 pthread_mutex_unlock(&out->lock);
2805 return ret;
2806 } else {
2807 if (out->pcm) {
2808 if (out->muted)
2809 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002810
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302811 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002812
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002813 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002814
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002815 if (out->config.rate)
2816 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2817 out->config.rate;
2818
2819 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2820
2821 request_out_focus(out, ns);
2822
2823 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002824 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002825 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302826 out->convert_buffer != NULL) {
2827
2828 memcpy_by_audio_format(out->convert_buffer,
2829 out->hal_op_format,
2830 buffer,
2831 out->hal_ip_format,
2832 out->config.period_size * out->config.channels);
2833
2834 ret = pcm_write(out->pcm, out->convert_buffer,
2835 (out->config.period_size *
2836 out->config.channels *
2837 format_to_bitwidth_table[out->hal_op_format]));
2838 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002839 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302840 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002841
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002842 release_out_focus(out);
2843
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302844 if (ret < 0)
2845 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302846 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2847 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2848 else
2849 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 }
2852
2853exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302854 /* ToDo: There may be a corner case when SSR happens back to back during
2855 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302856 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302857 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302858 }
2859
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 pthread_mutex_unlock(&out->lock);
2861
2862 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002863 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002864 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302865 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302866 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302867 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302868 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302869 out->standby = true;
2870 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302872 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302873 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 }
2875 return bytes;
2876}
2877
2878static int out_get_render_position(const struct audio_stream_out *stream,
2879 uint32_t *dsp_frames)
2880{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302882 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002883
2884 if (dsp_frames == NULL)
2885 return -EINVAL;
2886
2887 *dsp_frames = 0;
2888 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002889 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302890
2891 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2892 * this operation and adev_close_output_stream(where out gets reset).
2893 */
2894 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2895 *dsp_frames = get_actual_pcm_frames_rendered(out);
2896 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2897 return 0;
2898 }
2899
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002900 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302901 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302902 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302904 if (ret < 0)
2905 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302907 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 }
2909 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302910 if (-ENETRESET == ret) {
2911 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2912 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2913 return -EINVAL;
2914 } else if(ret < 0) {
2915 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2916 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302917 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2918 /*
2919 * Handle corner case where compress session is closed during SSR
2920 * and timestamp is queried
2921 */
2922 ALOGE(" ERROR: sound card not active, return error");
2923 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302924 } else {
2925 return 0;
2926 }
Zhou Song32a556e2015-05-05 10:46:56 +08002927 } else if (audio_is_linear_pcm(out->format)) {
2928 *dsp_frames = out->written;
2929 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 } else
2931 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932}
2933
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002934static int out_add_audio_effect(const struct audio_stream *stream __unused,
2935 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936{
2937 return 0;
2938}
2939
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002940static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2941 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942{
2943 return 0;
2944}
2945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002946static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2947 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948{
2949 return -EINVAL;
2950}
2951
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002952static int out_get_presentation_position(const struct audio_stream_out *stream,
2953 uint64_t *frames, struct timespec *timestamp)
2954{
2955 struct stream_out *out = (struct stream_out *)stream;
2956 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002957 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002958
Ashish Jain5106d362016-05-11 19:23:33 +05302959 /* below piece of code is not guarded against any lock because audioFliner serializes
2960 * this operation and adev_close_output_stream( where out gets reset).
2961 */
2962 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2963 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2964 *frames = get_actual_pcm_frames_rendered(out);
2965 /* this is the best we can do */
2966 clock_gettime(CLOCK_MONOTONIC, timestamp);
2967 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2968 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2969 return 0;
2970 }
2971
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002972 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002973
Ashish Jain5106d362016-05-11 19:23:33 +05302974 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2975 ret = compress_get_tstamp(out->compr, &dsp_frames,
2976 &out->sample_rate);
2977 ALOGVV("%s rendered frames %ld sample_rate %d",
2978 __func__, dsp_frames, out->sample_rate);
2979 *frames = dsp_frames;
2980 if (ret < 0)
2981 ret = -errno;
2982 if (-ENETRESET == ret) {
2983 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2984 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2985 ret = -EINVAL;
2986 } else
2987 ret = 0;
2988 /* this is the best we can do */
2989 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002990 } else {
2991 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002992 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002993 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2994 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002995 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002996 // This adjustment accounts for buffering after app processor.
2997 // It is based on estimated DSP latency per use case, rather than exact.
2998 signed_frames -=
2999 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3000
Eric Laurent949a0892013-09-20 09:20:13 -07003001 // It would be unusual for this value to be negative, but check just in case ...
3002 if (signed_frames >= 0) {
3003 *frames = signed_frames;
3004 ret = 0;
3005 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003006 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303007 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3008 *frames = out->written;
3009 clock_gettime(CLOCK_MONOTONIC, timestamp);
3010 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003011 }
3012 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003013 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003014 return ret;
3015}
3016
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017static int out_set_callback(struct audio_stream_out *stream,
3018 stream_callback_t callback, void *cookie)
3019{
3020 struct stream_out *out = (struct stream_out *)stream;
3021
3022 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003023 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003024 out->offload_callback = callback;
3025 out->offload_cookie = cookie;
3026 pthread_mutex_unlock(&out->lock);
3027 return 0;
3028}
3029
3030static int out_pause(struct audio_stream_out* stream)
3031{
3032 struct stream_out *out = (struct stream_out *)stream;
3033 int status = -ENOSYS;
3034 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003035 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003036 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003037 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303039 struct audio_device *adev = out->dev;
3040 int snd_scard_state = get_snd_card_state(adev);
3041
3042 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3043 status = compress_pause(out->compr);
3044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003045 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003046
Mingming Yin21854652016-04-13 11:54:02 -07003047 if (audio_extn_passthru_is_active()) {
3048 ALOGV("offload use case, pause passthru");
3049 audio_extn_passthru_on_pause(out);
3050 }
3051
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303052 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003053 audio_extn_dts_notify_playback_state(out->usecase, 0,
3054 out->sample_rate, popcount(out->channel_mask),
3055 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 }
3057 pthread_mutex_unlock(&out->lock);
3058 }
3059 return status;
3060}
3061
3062static int out_resume(struct audio_stream_out* stream)
3063{
3064 struct stream_out *out = (struct stream_out *)stream;
3065 int status = -ENOSYS;
3066 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003067 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003068 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003070 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303072 struct audio_device *adev = out->dev;
3073 int snd_scard_state = get_snd_card_state(adev);
3074
Mingming Yin21854652016-04-13 11:54:02 -07003075 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3076 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3077 pthread_mutex_lock(&out->dev->lock);
3078 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003079 pthread_mutex_unlock(&out->dev->lock);
3080 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303081 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003082 }
3083 if (!status) {
3084 out->offload_state = OFFLOAD_STATE_PLAYING;
3085 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303086 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003087 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3088 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 }
3090 pthread_mutex_unlock(&out->lock);
3091 }
3092 return status;
3093}
3094
3095static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3096{
3097 struct stream_out *out = (struct stream_out *)stream;
3098 int status = -ENOSYS;
3099 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003100 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003101 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3103 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3104 else
3105 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3106 pthread_mutex_unlock(&out->lock);
3107 }
3108 return status;
3109}
3110
3111static int out_flush(struct audio_stream_out* stream)
3112{
3113 struct stream_out *out = (struct stream_out *)stream;
3114 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003115 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003116 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003117 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303119 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003121 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 return 0;
3123 }
3124 return -ENOSYS;
3125}
3126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127/** audio_stream_in implementation **/
3128static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3129{
3130 struct stream_in *in = (struct stream_in *)stream;
3131
3132 return in->config.rate;
3133}
3134
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003135static int in_set_sample_rate(struct audio_stream *stream __unused,
3136 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137{
3138 return -ENOSYS;
3139}
3140
3141static size_t in_get_buffer_size(const struct audio_stream *stream)
3142{
3143 struct stream_in *in = (struct stream_in *)stream;
3144
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003145 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3146 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003147 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3148 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003149
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003150 return in->config.period_size * in->af_period_multiplier *
3151 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152}
3153
3154static uint32_t in_get_channels(const struct audio_stream *stream)
3155{
3156 struct stream_in *in = (struct stream_in *)stream;
3157
3158 return in->channel_mask;
3159}
3160
3161static audio_format_t in_get_format(const struct audio_stream *stream)
3162{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003163 struct stream_in *in = (struct stream_in *)stream;
3164
3165 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166}
3167
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003168static int in_set_format(struct audio_stream *stream __unused,
3169 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170{
3171 return -ENOSYS;
3172}
3173
3174static int in_standby(struct audio_stream *stream)
3175{
3176 struct stream_in *in = (struct stream_in *)stream;
3177 struct audio_device *adev = in->dev;
3178 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303179 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3180 stream, in->usecase, use_case_table[in->usecase]);
3181
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003182 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003183 if (!in->standby && in->is_st_session) {
3184 ALOGD("%s: sound trigger pcm stop lab", __func__);
3185 audio_extn_sound_trigger_stop_lab(in);
3186 in->standby = 1;
3187 }
3188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003190 if (adev->adm_deregister_stream)
3191 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3192
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003193 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003195 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3196 voice_extn_compress_voip_close_input_stream(stream);
3197 ALOGD("VOIP input entered standby");
3198 } else {
3199 if (in->pcm) {
3200 pcm_close(in->pcm);
3201 in->pcm = NULL;
3202 }
3203 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003204 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003205 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 }
3207 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003208 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 return status;
3210}
3211
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003212static int in_dump(const struct audio_stream *stream __unused,
3213 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214{
3215 return 0;
3216}
3217
3218static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3219{
3220 struct stream_in *in = (struct stream_in *)stream;
3221 struct audio_device *adev = in->dev;
3222 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003224 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303226 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 parms = str_parms_create_str(kvpairs);
3228
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303229 if (!parms)
3230 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003231 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003232 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003233
3234 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3235 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 val = atoi(value);
3237 /* no audio source uses val == 0 */
3238 if ((in->source != val) && (val != 0)) {
3239 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003240 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3241 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3242 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003243 (in->config.rate == 8000 || in->config.rate == 16000 ||
3244 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003245 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003246 err = voice_extn_compress_voip_open_input_stream(in);
3247 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003248 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003249 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003250 }
3251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 }
3253 }
3254
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003255 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3256 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003258 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 in->device = val;
3260 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003261 if (!in->standby && !in->is_st_session) {
3262 ALOGV("update input routing change");
3263 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003264 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 }
3267 }
3268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003270 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271
3272 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303273error:
Eric Laurent994a6932013-07-17 11:51:42 -07003274 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275 return ret;
3276}
3277
3278static char* in_get_parameters(const struct audio_stream *stream,
3279 const char *keys)
3280{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003281 struct stream_in *in = (struct stream_in *)stream;
3282 struct str_parms *query = str_parms_create_str(keys);
3283 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003284 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003285
3286 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003287 if (reply) {
3288 str_parms_destroy(reply);
3289 }
3290 if (query) {
3291 str_parms_destroy(query);
3292 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003293 ALOGE("in_get_parameters: failed to create query or reply");
3294 return NULL;
3295 }
3296
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003297 ALOGV("%s: enter: keys - %s", __func__, keys);
3298
3299 voice_extn_in_get_parameters(in, query, reply);
3300
3301 str = str_parms_to_str(reply);
3302 str_parms_destroy(query);
3303 str_parms_destroy(reply);
3304
3305 ALOGV("%s: exit: returns - %s", __func__, str);
3306 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307}
3308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003309static int in_set_gain(struct audio_stream_in *stream __unused,
3310 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311{
3312 return 0;
3313}
3314
3315static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3316 size_t bytes)
3317{
3318 struct stream_in *in = (struct stream_in *)stream;
3319 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303320 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303321 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303322 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003324 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303325
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003326 if (in->is_st_session) {
3327 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3328 /* Read from sound trigger HAL */
3329 audio_extn_sound_trigger_read(in, buffer, bytes);
3330 pthread_mutex_unlock(&in->lock);
3331 return bytes;
3332 }
3333
Ashish Jainbbce4322016-02-16 13:25:27 +05303334 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003335 ALOGD(" %s: sound card is not active/SSR state", __func__);
3336 ret= -EIO;;
3337 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303338 }
3339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003341 pthread_mutex_lock(&adev->lock);
3342 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3343 ret = voice_extn_compress_voip_start_input_stream(in);
3344 else
3345 ret = start_input_stream(in);
3346 pthread_mutex_unlock(&adev->lock);
3347 if (ret != 0) {
3348 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 }
3350 in->standby = 0;
3351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003353 // what's the duration requested by the client?
3354 long ns = 0;
3355
3356 if (in->config.rate)
3357 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3358 in->config.rate;
3359
3360 request_in_focus(in, ns);
3361 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303364 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003365 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303366 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003367 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003368 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003369 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303370 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003371 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303372 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3373 if (bytes % 4 == 0) {
3374 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3375 int_buf_stream = buffer;
3376 for (size_t itt=0; itt < bytes/4 ; itt++) {
3377 int_buf_stream[itt] >>= 8;
3378 }
3379 } else {
3380 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3381 ret = -EINVAL;
3382 goto exit;
3383 }
3384 } if (ret < 0) {
3385 ret = -errno;
3386 }
3387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 }
3389
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003390 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 /*
3393 * Instead of writing zeroes here, we could trust the hardware
3394 * to always provide zeroes when muted.
3395 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303396 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3397 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 memset(buffer, 0, bytes);
3399
3400exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303401 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303402 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003403 if (-ENETRESET == ret)
3404 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 pthread_mutex_unlock(&in->lock);
3407
3408 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303409 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303410 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303411 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303412 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303413 in->standby = true;
3414 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303415 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003417 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303418 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303419 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 }
3421 return bytes;
3422}
3423
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003424static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425{
3426 return 0;
3427}
3428
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003429static int add_remove_audio_effect(const struct audio_stream *stream,
3430 effect_handle_t effect,
3431 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003433 struct stream_in *in = (struct stream_in *)stream;
3434 int status = 0;
3435 effect_descriptor_t desc;
3436
3437 status = (*effect)->get_descriptor(effect, &desc);
3438 if (status != 0)
3439 return status;
3440
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003441 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003442 pthread_mutex_lock(&in->dev->lock);
3443 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3444 in->enable_aec != enable &&
3445 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3446 in->enable_aec = enable;
3447 if (!in->standby)
3448 select_devices(in->dev, in->usecase);
3449 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003450 if (in->enable_ns != enable &&
3451 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3452 in->enable_ns = enable;
3453 if (!in->standby)
3454 select_devices(in->dev, in->usecase);
3455 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003456 pthread_mutex_unlock(&in->dev->lock);
3457 pthread_mutex_unlock(&in->lock);
3458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 return 0;
3460}
3461
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003462static int in_add_audio_effect(const struct audio_stream *stream,
3463 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464{
Eric Laurent994a6932013-07-17 11:51:42 -07003465 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003466 return add_remove_audio_effect(stream, effect, true);
3467}
3468
3469static int in_remove_audio_effect(const struct audio_stream *stream,
3470 effect_handle_t effect)
3471{
Eric Laurent994a6932013-07-17 11:51:42 -07003472 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003473 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474}
3475
3476static int adev_open_output_stream(struct audio_hw_device *dev,
3477 audio_io_handle_t handle,
3478 audio_devices_t devices,
3479 audio_output_flags_t flags,
3480 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003481 struct audio_stream_out **stream_out,
3482 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483{
3484 struct audio_device *adev = (struct audio_device *)dev;
3485 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303486 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003487 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303490
3491 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3492 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003493 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303494 return -EINVAL;
3495 }
3496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3498
Mingming Yin3a941d42016-02-17 18:08:05 -08003499 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3500 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303501 devices, flags, &out->stream);
3502
3503
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003504 if (!out) {
3505 return -ENOMEM;
3506 }
3507
Haynes Mathew George204045b2015-02-25 20:32:03 -08003508 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003509 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003510 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 if (devices == AUDIO_DEVICE_NONE)
3513 devices = AUDIO_DEVICE_OUT_SPEAKER;
3514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 out->flags = flags;
3516 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003517 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003518 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 out->sample_rate = config->sample_rate;
3520 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3521 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003522 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003523 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003524 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303525 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526
Mingming Yin3a941d42016-02-17 18:08:05 -08003527 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3528 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3529 pthread_mutex_lock(&adev->lock);
3530 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3531 ret = read_hdmi_sink_caps(out);
3532 pthread_mutex_unlock(&adev->lock);
3533 if (ret != 0) {
3534 if (ret == -ENOSYS) {
3535 /* ignore and go with default */
3536 ret = 0;
3537 } else {
3538 ALOGE("error reading hdmi sink caps");
3539 goto error_open;
3540 }
3541 }
3542 }
3543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003545 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303546 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3547 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003548 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3549 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3550
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003551 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003552 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3553 /*
3554 * Do not handle stereo output in Multi-channel cases
3555 * Stereo case is handled in normal playback path
3556 */
3557 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3558 ret = AUDIO_CHANNEL_OUT_STEREO;
3559 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003560
3561 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3562 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003563 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003564 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003565 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003566
3567 if (config->sample_rate == 0)
3568 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3569 if (config->channel_mask == 0)
3570 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003571 if (config->format == 0)
3572 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003573
3574 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003575 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003576 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3578 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003580 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003582 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3583 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003584 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003585 ret = voice_extn_compress_voip_open_output_stream(out);
3586 if (ret != 0) {
3587 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3588 __func__, ret);
3589 goto error_open;
3590 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003591 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3592 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3593
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003594 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3595 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3596 ALOGE("%s: Unsupported Offload information", __func__);
3597 ret = -EINVAL;
3598 goto error_open;
3599 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003600
Mingming Yin3a941d42016-02-17 18:08:05 -08003601 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003602 if(config->offload_info.format == 0)
3603 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003604 if (config->offload_info.sample_rate == 0)
3605 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003606 }
3607
Mingming Yin90310102013-11-13 16:57:00 -08003608 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303609 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003610 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003611 ret = -EINVAL;
3612 goto error_open;
3613 }
3614
3615 out->compr_config.codec = (struct snd_codec *)
3616 calloc(1, sizeof(struct snd_codec));
3617
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003618 if (!out->compr_config.codec) {
3619 ret = -ENOMEM;
3620 goto error_open;
3621 }
3622
vivek mehta0ea887a2015-08-26 14:01:20 -07003623 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303624 out->stream.pause = out_pause;
3625 out->stream.flush = out_flush;
3626 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003627 out->usecase = get_offload_usecase(adev, true);
3628 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003629 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003630 out->stream.set_callback = out_set_callback;
3631 out->stream.pause = out_pause;
3632 out->stream.resume = out_resume;
3633 out->stream.drain = out_drain;
3634 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003635 out->usecase = get_offload_usecase(adev, false);
3636 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003637 }
vivek mehta446c3962015-09-14 10:57:35 -07003638
3639 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003640 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3641 config->format == 0 && config->sample_rate == 0 &&
3642 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003643 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003644 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3645 } else {
3646 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3647 ret = -EEXIST;
3648 goto error_open;
3649 }
vivek mehta446c3962015-09-14 10:57:35 -07003650 }
3651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 if (config->offload_info.channel_mask)
3653 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003654 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003655 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003656 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003657 } else {
3658 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3659 ret = -EINVAL;
3660 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003661 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003662
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003663 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 out->sample_rate = config->offload_info.sample_rate;
3665
Mingming Yin3ee55c62014-08-04 14:23:35 -07003666 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003667
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303668 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3669 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3670 audio_extn_dolby_send_ddp_endp_params(adev);
3671 audio_extn_dolby_set_dmid(adev);
3672 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003675 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 out->compr_config.codec->bit_rate =
3677 config->offload_info.bit_rate;
3678 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303679 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003680 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303681 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003682 /*TODO: Do we need to change it for passthrough */
3683 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684
Manish Dewangana6fc5442015-08-24 20:30:31 +05303685 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3686 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3687 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3688 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303689
3690 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3691 AUDIO_FORMAT_PCM) {
3692
3693 /*Based on platform support, configure appropriate alsa format for corresponding
3694 *hal input format.
3695 */
3696 out->compr_config.codec->format = hal_format_to_alsa(
3697 config->offload_info.format);
3698
Ashish Jain83a6cc22016-06-28 14:34:17 +05303699 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303700 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303701 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303702
3703 /*for direct PCM playback populate bit_width based on selected alsa format as
3704 *hal input format and alsa format might differ based on platform support.
3705 */
3706 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303707 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303708
3709 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3710
3711 /* Check if alsa session is configured with the same format as HAL input format,
3712 * if not then derive correct fragment size needed to accomodate the
3713 * conversion of HAL input format to alsa format.
3714 */
3715 audio_extn_utils_update_direct_pcm_fragment_size(out);
3716
3717 /*if hal input and output fragment size is different this indicates HAL input format is
3718 *not same as the alsa format
3719 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303720 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303721 /*Allocate a buffer to convert input data to the alsa configured format.
3722 *size of convert buffer is equal to the size required to hold one fragment size
3723 *worth of pcm data, this is because flinger does not write more than fragment_size
3724 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303725 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3726 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303727 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3728 ret = -ENOMEM;
3729 goto error_open;
3730 }
3731 }
3732 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3733 out->compr_config.fragment_size =
3734 audio_extn_passthru_get_buffer_size(&config->offload_info);
3735 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3736 } else {
3737 out->compr_config.fragment_size =
3738 platform_get_compress_offload_buffer_size(&config->offload_info);
3739 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3740 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003741
Amit Shekhar6f461b12014-08-01 14:52:58 -07003742 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303743 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3746 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003747
Alexy Josephaa54c872014-12-03 02:46:47 -08003748
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003749 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303750 out->send_next_track_params = false;
3751 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003752 out->offload_state = OFFLOAD_STATE_IDLE;
3753 out->playback_started = 0;
3754
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003755 audio_extn_dts_create_state_notifier_node(out->usecase);
3756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 create_offload_callback_thread(out);
3758 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3759 __func__, config->offload_info.version,
3760 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303761
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303762 /*Check if DSD audio format is supported in codec
3763 *and there is no active native DSD use case
3764 */
3765
3766 if ((config->format == AUDIO_FORMAT_DSD) &&
3767 (!platform_check_codec_dsd_support(adev->platform) ||
3768 audio_is_dsd_native_stream_active(adev))) {
3769 ret = -EINVAL;
3770 goto error_open;
3771 }
3772
Ashish Jain5106d362016-05-11 19:23:33 +05303773 /* Disable gapless if any of the following is true
3774 * passthrough playback
3775 * AV playback
3776 * Direct PCM playback
3777 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303778 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303779 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303780 config->offload_info.has_video ||
3781 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3782 check_and_set_gapless_mode(adev, false);
3783 } else
3784 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003785
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303786 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003787 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3788 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303789 if (config->format == AUDIO_FORMAT_DSD) {
3790 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3791 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3792 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003793 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303794 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003795 if (ret != 0) {
3796 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3797 __func__, ret);
3798 goto error_open;
3799 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003800 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3801 if (config->sample_rate == 0)
3802 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3803 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3804 config->sample_rate != 8000) {
3805 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3806 ret = -EINVAL;
3807 goto error_open;
3808 }
3809 out->sample_rate = config->sample_rate;
3810 out->config.rate = config->sample_rate;
3811 if (config->format == AUDIO_FORMAT_DEFAULT)
3812 config->format = AUDIO_FORMAT_PCM_16_BIT;
3813 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3814 config->format = AUDIO_FORMAT_PCM_16_BIT;
3815 ret = -EINVAL;
3816 goto error_open;
3817 }
3818 out->format = config->format;
3819 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3820 out->config = pcm_config_afe_proxy_playback;
3821 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003822 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303823 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3824 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003825 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3826 out->flags);
3827 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303828 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3829 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3830 out->config = pcm_config_low_latency;
3831 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3832 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3833 out->config = pcm_config_deep_buffer;
3834 } else {
3835 /* primary path is the default path selected if no other outputs are available/suitable */
3836 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3837 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3838 }
3839 out->hal_ip_format = format = out->format;
3840 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3841 out->hal_op_format = pcm_format_to_hal(out->config.format);
3842 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3843 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003844 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303845 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3846 if (out->hal_ip_format != out->hal_op_format) {
3847 uint32_t buffer_size = out->config.period_size *
3848 format_to_bitwidth_table[out->hal_op_format] *
3849 out->config.channels;
3850 out->convert_buffer = calloc(1, buffer_size);
3851 if (out->convert_buffer == NULL){
3852 ALOGE("Allocation failed for convert buffer for size %d",
3853 out->compr_config.fragment_size);
3854 ret = -ENOMEM;
3855 goto error_open;
3856 }
3857 ALOGD("Convert buffer allocated of size %d", buffer_size);
3858 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 }
3860
Ashish Jain83a6cc22016-06-28 14:34:17 +05303861 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3862 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3863
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003864 /* TODO remove this hardcoding and check why width is zero*/
3865 if (out->bit_width == 0)
3866 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003867 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3868 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003869 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303870 out->bit_width, out->channel_mask,
3871 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003872 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3873 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3874 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003875 if(adev->primary_output == NULL)
3876 adev->primary_output = out;
3877 else {
3878 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003879 ret = -EEXIST;
3880 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003881 }
3882 }
3883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 /* Check if this usecase is already existing */
3885 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003886 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3887 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003890 ret = -EEXIST;
3891 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892 }
3893 pthread_mutex_unlock(&adev->lock);
3894
3895 out->stream.common.get_sample_rate = out_get_sample_rate;
3896 out->stream.common.set_sample_rate = out_set_sample_rate;
3897 out->stream.common.get_buffer_size = out_get_buffer_size;
3898 out->stream.common.get_channels = out_get_channels;
3899 out->stream.common.get_format = out_get_format;
3900 out->stream.common.set_format = out_set_format;
3901 out->stream.common.standby = out_standby;
3902 out->stream.common.dump = out_dump;
3903 out->stream.common.set_parameters = out_set_parameters;
3904 out->stream.common.get_parameters = out_get_parameters;
3905 out->stream.common.add_audio_effect = out_add_audio_effect;
3906 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3907 out->stream.get_latency = out_get_latency;
3908 out->stream.set_volume = out_set_volume;
3909 out->stream.write = out_write;
3910 out->stream.get_render_position = out_get_render_position;
3911 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003912 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003914 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003916 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003917 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918
3919 config->format = out->stream.common.get_format(&out->stream.common);
3920 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3921 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3922
3923 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303924 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003925 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003926
3927 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3928 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3929 popcount(out->channel_mask), out->playback_started);
3930
Eric Laurent994a6932013-07-17 11:51:42 -07003931 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003933
3934error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303935 if (out->convert_buffer)
3936 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003937 free(out);
3938 *stream_out = NULL;
3939 ALOGD("%s: exit: ret %d", __func__, ret);
3940 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941}
3942
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003943static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 struct audio_stream_out *stream)
3945{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003946 struct stream_out *out = (struct stream_out *)stream;
3947 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003948 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303950 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3951
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003952 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303953 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003954 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303955 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003956 if(ret != 0)
3957 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3958 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003959 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003960 out_standby(&stream->common);
3961
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003962 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003963 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003965 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003966 if (out->compr_config.codec != NULL)
3967 free(out->compr_config.codec);
3968 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003969
Ashish Jain83a6cc22016-06-28 14:34:17 +05303970 if (out->convert_buffer != NULL) {
3971 free(out->convert_buffer);
3972 out->convert_buffer = NULL;
3973 }
3974
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003975 if (adev->voice_tx_output == out)
3976 adev->voice_tx_output = NULL;
3977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978 pthread_cond_destroy(&out->cond);
3979 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003981 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982}
3983
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003984static void close_compress_sessions(struct audio_device *adev)
3985{
Mingming Yin7b762e72015-03-04 13:47:32 -08003986 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303987 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003988 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003989 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303990
3991 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003992 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303993 if (is_offload_usecase(usecase->id)) {
3994 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003995 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3996 out = usecase->stream.out;
3997 pthread_mutex_unlock(&adev->lock);
3998 out_standby(&out->stream.common);
3999 pthread_mutex_lock(&adev->lock);
4000 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304001 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004002 }
4003 pthread_mutex_unlock(&adev->lock);
4004}
4005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4007{
4008 struct audio_device *adev = (struct audio_device *)dev;
4009 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004011 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004012 int ret;
4013 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004015 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304018 if (!parms)
4019 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004020 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4021 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304022 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304023 if (strstr(snd_card_status, "OFFLINE")) {
4024 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304025 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004026 //close compress sessions on OFFLINE status
4027 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304028 } else if (strstr(snd_card_status, "ONLINE")) {
4029 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304030 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004031 //send dts hpx license if enabled
4032 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304033 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304034 }
4035
4036 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004037 status = voice_set_parameters(adev, parms);
4038 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004039 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004041 status = platform_set_parameters(adev->platform, parms);
4042 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004043 goto done;
4044
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004045 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4046 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004047 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4049 adev->bluetooth_nrec = true;
4050 else
4051 adev->bluetooth_nrec = false;
4052 }
4053
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004054 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4055 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4057 adev->screen_off = false;
4058 else
4059 adev->screen_off = true;
4060 }
4061
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004062 ret = str_parms_get_int(parms, "rotation", &val);
4063 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004064 bool reverse_speakers = false;
4065 switch(val) {
4066 // FIXME: note that the code below assumes that the speakers are in the correct placement
4067 // relative to the user when the device is rotated 90deg from its default rotation. This
4068 // assumption is device-specific, not platform-specific like this code.
4069 case 270:
4070 reverse_speakers = true;
4071 break;
4072 case 0:
4073 case 90:
4074 case 180:
4075 break;
4076 default:
4077 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004078 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004079 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004080 if (status == 0) {
4081 if (adev->speaker_lr_swap != reverse_speakers) {
4082 adev->speaker_lr_swap = reverse_speakers;
4083 // only update the selected device if there is active pcm playback
4084 struct audio_usecase *usecase;
4085 struct listnode *node;
4086 list_for_each(node, &adev->usecase_list) {
4087 usecase = node_to_item(node, struct audio_usecase, list);
4088 if (usecase->type == PCM_PLAYBACK) {
4089 select_devices(adev, usecase->id);
4090 break;
4091 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004092 }
4093 }
4094 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004095 }
4096
Mingming Yin514a8bc2014-07-29 15:22:21 -07004097 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4098 if (ret >= 0) {
4099 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4100 adev->bt_wb_speech_enabled = true;
4101 else
4102 adev->bt_wb_speech_enabled = false;
4103 }
4104
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004105 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4106 if (ret >= 0) {
4107 val = atoi(value);
4108 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4109 ALOGV("cache new edid");
4110 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004111 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004112 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004113 /*
4114 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4115 * Per AudioPolicyManager, USB device is higher priority than WFD.
4116 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4117 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4118 * starting voice call on USB
4119 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004120 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4121 if (ret >= 0) {
4122 audio_extn_usb_add_device(val, atoi(value));
4123 }
vivek mehta344576a2016-04-12 18:56:03 -07004124 ALOGV("detected USB connect .. disable proxy");
4125 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004126 }
4127 }
4128
4129 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4130 if (ret >= 0) {
4131 val = atoi(value);
4132 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4133 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004134 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004135 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004136 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004137 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4138 if (ret >= 0) {
4139 audio_extn_usb_remove_device(val, atoi(value));
4140 }
vivek mehta344576a2016-04-12 18:56:03 -07004141 ALOGV("detected USB disconnect .. enable proxy");
4142 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004143 }
4144 }
4145
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304146 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4147 if (ret >= 0) {
4148 struct audio_usecase *usecase;
4149 struct listnode *node;
4150 list_for_each(node, &adev->usecase_list) {
4151 usecase = node_to_item(node, struct audio_usecase, list);
4152 if ((usecase->type == PCM_PLAYBACK) &&
4153 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4154 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304155 lock_output_stream(usecase->stream.out);
4156 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304157 //force device switch to re configure encoder
4158 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304159 audio_extn_a2dp_set_handoff_mode(false);
4160 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304161 break;
4162 }
4163 }
4164 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304165 audio_extn_set_parameters(adev, parms);
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};