blob: b617407beffbf4c5c589eb03c68284abd7219093 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700258};
259
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700260static const audio_usecase_t offload_usecases[] = {
261 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700262 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
263 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800271
272#define STRING_TO_ENUM(string) { #string, string }
273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800274struct string_to_enum {
275 const char *name;
276 uint32_t value;
277};
278
279static const struct string_to_enum out_channels_name_to_enum_table[] = {
280 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
288};
289
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700290static const struct string_to_enum out_formats_name_to_enum_table[] = {
291 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
292 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800294 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
295 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
296};
297
298//list of all supported sample rates by HDMI specification.
299static const int out_hdmi_sample_rates[] = {
300 32000, 44100, 48000, 88200, 96000, 176400, 192000,
301};
302
303static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
304 STRING_TO_ENUM(32000),
305 STRING_TO_ENUM(44100),
306 STRING_TO_ENUM(48000),
307 STRING_TO_ENUM(88200),
308 STRING_TO_ENUM(96000),
309 STRING_TO_ENUM(176400),
310 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700311};
312
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700313static struct audio_device *adev = NULL;
314static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700315static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700316//cache last MBDRC cal step level
317static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700318
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700319static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
320 int flags __unused)
321{
322 int dir = 0;
323 switch (uc_id) {
324 case USECASE_AUDIO_RECORD_LOW_LATENCY:
325 dir = 1;
326 case USECASE_AUDIO_PLAYBACK_ULL:
327 break;
328 default:
329 return false;
330 }
331
332 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
333 PCM_PLAYBACK : PCM_CAPTURE);
334 if (adev->adm_is_noirq_avail)
335 return adev->adm_is_noirq_avail(adev->adm_data,
336 adev->snd_card, dev_id, dir);
337 return false;
338}
339
340static void register_out_stream(struct stream_out *out)
341{
342 struct audio_device *adev = out->dev;
343 if (is_offload_usecase(out->usecase) ||
344 !adev->adm_register_output_stream)
345 return;
346
347 // register stream first for backward compatibility
348 adev->adm_register_output_stream(adev->adm_data,
349 out->handle,
350 out->flags);
351
352 if (!adev->adm_set_config)
353 return;
354
355 if (out->realtime)
356 adev->adm_set_config(adev->adm_data,
357 out->handle,
358 out->pcm, &out->config);
359}
360
361static void register_in_stream(struct stream_in *in)
362{
363 struct audio_device *adev = in->dev;
364 if (!adev->adm_register_input_stream)
365 return;
366
367 adev->adm_register_input_stream(adev->adm_data,
368 in->capture_handle,
369 in->flags);
370
371 if (!adev->adm_set_config)
372 return;
373
374 if (in->realtime)
375 adev->adm_set_config(adev->adm_data,
376 in->capture_handle,
377 in->pcm,
378 &in->config);
379}
380
381static void request_out_focus(struct stream_out *out, long ns)
382{
383 struct audio_device *adev = out->dev;
384
385 if (out->routing_change) {
386 out->routing_change = false;
387 // must be checked for backward compatibility
388 if (adev->adm_on_routing_change)
389 adev->adm_on_routing_change(adev->adm_data, out->handle);
390 }
391
392 if (adev->adm_request_focus_v2)
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 else if (adev->adm_request_focus)
395 adev->adm_request_focus(adev->adm_data, out->handle);
396}
397
398static void request_in_focus(struct stream_in *in, long ns)
399{
400 struct audio_device *adev = in->dev;
401
402 if (in->routing_change) {
403 in->routing_change = false;
404 if (adev->adm_on_routing_change)
405 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
406 }
407
408 if (adev->adm_request_focus_v2)
409 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
410 else if (adev->adm_request_focus)
411 adev->adm_request_focus(adev->adm_data, in->capture_handle);
412}
413
414static void release_out_focus(struct stream_out *out)
415{
416 struct audio_device *adev = out->dev;
417
418 if (adev->adm_abandon_focus)
419 adev->adm_abandon_focus(adev->adm_data, out->handle);
420}
421
422static void release_in_focus(struct stream_in *in)
423{
424 struct audio_device *adev = in->dev;
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
427}
428
vivek mehtaa76401a2015-04-24 14:12:15 -0700429__attribute__ ((visibility ("default")))
430bool audio_hw_send_gain_dep_calibration(int level) {
431 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700432 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700433
434 pthread_mutex_lock(&adev_init_lock);
435
436 if (adev != NULL && adev->platform != NULL) {
437 pthread_mutex_lock(&adev->lock);
438 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700439
440 // if cal set fails, cache level info
441 // if cal set succeds, reset known last cal set
442 if (!ret_val)
443 last_known_cal_step = level;
444 else if (last_known_cal_step != -1)
445 last_known_cal_step = -1;
446
vivek mehtaa76401a2015-04-24 14:12:15 -0700447 pthread_mutex_unlock(&adev->lock);
448 } else {
449 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
450 }
451
452 pthread_mutex_unlock(&adev_init_lock);
453
454 return ret_val;
455}
456
Ashish Jain5106d362016-05-11 19:23:33 +0530457static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
458{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459 bool gapless_enabled = false;
460 const char *mixer_ctl_name = "Compress Gapless Playback";
461 struct mixer_ctl *ctl;
462
463 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530464 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
465
466 /*Disable gapless if its AV playback*/
467 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800468
469 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
470 if (!ctl) {
471 ALOGE("%s: Could not get ctl for mixer cmd - %s",
472 __func__, mixer_ctl_name);
473 return -EINVAL;
474 }
475
476 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
477 ALOGE("%s: Could not set gapless mode %d",
478 __func__, gapless_enabled);
479 return -EINVAL;
480 }
481 return 0;
482}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700483
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700484static bool is_supported_format(audio_format_t format)
485{
Eric Laurent86e17132013-09-12 17:49:30 -0700486 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530487 format == AUDIO_FORMAT_AAC_LC ||
488 format == AUDIO_FORMAT_AAC_HE_V1 ||
489 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530490 format == AUDIO_FORMAT_AAC_ADTS_LC ||
491 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530493 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
494 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530495 format == AUDIO_FORMAT_PCM_FLOAT ||
496 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700497 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530498 format == AUDIO_FORMAT_AC3 ||
499 format == AUDIO_FORMAT_E_AC3 ||
500 format == AUDIO_FORMAT_DTS ||
501 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800502 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530503 format == AUDIO_FORMAT_ALAC ||
504 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530505 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530506 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800507 format == AUDIO_FORMAT_WMA ||
508 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800509 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700510
511 return false;
512}
513
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700514static inline bool is_mmap_usecase(audio_usecase_t uc_id)
515{
516 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
517 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
518}
519
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520static int get_snd_codec_id(audio_format_t format)
521{
522 int id = 0;
523
Ashish Jainf9b78162014-08-25 20:36:25 +0530524 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525 case AUDIO_FORMAT_MP3:
526 id = SND_AUDIOCODEC_MP3;
527 break;
528 case AUDIO_FORMAT_AAC:
529 id = SND_AUDIOCODEC_AAC;
530 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530531 case AUDIO_FORMAT_AAC_ADTS:
532 id = SND_AUDIOCODEC_AAC;
533 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700534 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800535 id = SND_AUDIOCODEC_PCM;
536 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700537 case AUDIO_FORMAT_FLAC:
538 id = SND_AUDIOCODEC_FLAC;
539 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530540 case AUDIO_FORMAT_ALAC:
541 id = SND_AUDIOCODEC_ALAC;
542 break;
543 case AUDIO_FORMAT_APE:
544 id = SND_AUDIOCODEC_APE;
545 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530546 case AUDIO_FORMAT_DSD:
547 id = SND_AUDIOCODEC_DSD;
548 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530549 case AUDIO_FORMAT_VORBIS:
550 id = SND_AUDIOCODEC_VORBIS;
551 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800552 case AUDIO_FORMAT_WMA:
553 id = SND_AUDIOCODEC_WMA;
554 break;
555 case AUDIO_FORMAT_WMA_PRO:
556 id = SND_AUDIOCODEC_WMA_PRO;
557 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530558 case AUDIO_FORMAT_AC3:
559 id = SND_AUDIOCODEC_AC3;
560 break;
561 case AUDIO_FORMAT_E_AC3:
562 case AUDIO_FORMAT_E_AC3_JOC:
563 id = SND_AUDIOCODEC_EAC3;
564 break;
565 case AUDIO_FORMAT_DTS:
566 case AUDIO_FORMAT_DTS_HD:
567 id = SND_AUDIOCODEC_DTS;
568 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700569 default:
Mingming Yin90310102013-11-13 16:57:00 -0800570 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700571 }
572
573 return id;
574}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800575
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530576int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530577{
578 int snd_scard_state;
579
580 if (!adev)
581 return SND_CARD_STATE_OFFLINE;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
584 snd_scard_state = adev->snd_card_status.state;
585 pthread_mutex_unlock(&adev->snd_card_status.lock);
586
587 return snd_scard_state;
588}
589
590static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
591{
592 if (!adev)
593 return -ENOSYS;
594
595 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700596 if (adev->snd_card_status.state != snd_scard_state) {
597 adev->snd_card_status.state = snd_scard_state;
598 platform_snd_card_update(adev->platform, snd_scard_state);
599 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530600 pthread_mutex_unlock(&adev->snd_card_status.lock);
601
602 return 0;
603}
604
Avinash Vaish71a8b972014-07-24 15:36:33 +0530605static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
606 struct audio_usecase *uc_info)
607{
608 struct listnode *node;
609 struct audio_usecase *usecase;
610
611 if (uc_info == NULL)
612 return -EINVAL;
613
614 /* Re-route all voice usecases on the shared backend other than the
615 specified usecase to new snd devices */
616 list_for_each(node, &adev->usecase_list) {
617 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800618 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530619 enable_audio_route(adev, usecase);
620 }
621 return 0;
622}
623
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530624/*
625 * Enable ASRC mode if native or DSD stream is active.
626 */
627static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
628{
629 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
630 !adev->asrc_mode_enabled) {
631 struct listnode *node = NULL;
632 struct audio_usecase *uc = NULL;
633 struct stream_out *curr_out = NULL;
634
635 list_for_each(node, &adev->usecase_list) {
636 uc = node_to_item(node, struct audio_usecase, list);
637 curr_out = (struct stream_out*) uc->stream.out;
638
639 if (curr_out && PCM_PLAYBACK == uc->type) {
640 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
641 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
642 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
643 __func__);
644 audio_route_apply_and_update_path(adev->audio_route,
645 "asrc-mode");
646 adev->asrc_mode_enabled = true;
647 break;
648 }
649 }
650 }
651 }
652}
653
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700654int pcm_ioctl(struct pcm *pcm, int request, ...)
655{
656 va_list ap;
657 void * arg;
658 int pcm_fd = *(int*)pcm;
659
660 va_start(ap, request);
661 arg = va_arg(ap, void *);
662 va_end(ap);
663
664 return ioctl(pcm_fd, request, arg);
665}
666
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700667int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700668 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700671 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800672
673 if (usecase == NULL)
674 return -EINVAL;
675
676 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
677
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800678 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800682
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800683#ifdef DS1_DOLBY_DAP_ENABLED
684 audio_extn_dolby_set_dmid(adev);
685 audio_extn_dolby_set_endpoint(adev);
686#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700687 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700688 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530689 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700690 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530691 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800692 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700693 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700694 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800696 ALOGV("%s: exit", __func__);
697 return 0;
698}
699
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700700int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700701 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700704 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800705
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530706 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800707 return -EINVAL;
708
709 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (usecase->type == PCM_CAPTURE)
711 snd_device = usecase->in_snd_device;
712 else
713 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800714 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700715 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700716 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700717 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700718 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530719 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720 ALOGV("%s: exit", __func__);
721 return 0;
722}
723
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700724int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700729 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
730
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800731 if (snd_device < SND_DEVICE_MIN ||
732 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800733 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800734 return -EINVAL;
735 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736
737 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700738
739 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
740 ALOGE("%s: Invalid sound device returned", __func__);
741 return -EINVAL;
742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700743 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700744 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700745 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 return 0;
747 }
748
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530749
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700750 if (audio_extn_spkr_prot_is_enabled())
751 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700752
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530754 if (((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
755 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
756 && (audio_extn_a2dp_start_playback() < 0)) {
757 ALOGE(" fail to configure A2dp control path ");
758 return -EINVAL;
759 }
760
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800761 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
762 audio_extn_spkr_prot_is_enabled()) {
763 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700764 adev->snd_dev_ref_cnt[snd_device]--;
765 return -EINVAL;
766 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200767 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800768 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800769 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200770 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 return -EINVAL;
772 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530773 } else if (platform_can_split_snd_device(adev->platform, snd_device,
774 &num_devices, new_snd_devices)) {
775 for (i = 0; i < num_devices; i++) {
776 enable_snd_device(adev, new_snd_devices[i]);
777 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800778 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700779 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700780 /* due to the possibility of calibration overwrite between listen
781 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700782 audio_extn_sound_trigger_update_device_status(snd_device,
783 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530784 audio_extn_listen_update_device_status(snd_device,
785 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700786 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 audio_extn_sound_trigger_update_device_status(snd_device,
789 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530790 audio_extn_listen_update_device_status(snd_device,
791 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700792 return -EINVAL;
793 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300794 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
797 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
798 !adev->native_playback_enabled &&
799 audio_is_true_native_stream_active(adev)) {
800 ALOGD("%s: %d: napb: enabling native mode in hardware",
801 __func__, __LINE__);
802 audio_route_apply_and_update_path(adev->audio_route,
803 "true-native-mode");
804 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530805 } else
806 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530814 int i, num_devices = 0;
815 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 if (snd_device < SND_DEVICE_MIN ||
819 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 return -EINVAL;
822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
824 ALOGE("%s: device ref cnt is already 0", __func__);
825 return -EINVAL;
826 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700829
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
831 ALOGE("%s: Invalid sound device returned", __func__);
832 return -EINVAL;
833 }
834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700836 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530837
838 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
839 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
840 audio_extn_a2dp_stop_playback();
841
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800842 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
843 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700844 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530845 } else if (platform_can_split_snd_device(adev->platform, snd_device,
846 &num_devices, new_snd_devices)) {
847 for (i = 0; i < num_devices; i++) {
848 disable_snd_device(adev, new_snd_devices[i]);
849 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300850 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700851 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 if (snd_device == SND_DEVICE_OUT_HDMI)
855 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530856 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
857 adev->native_playback_enabled) {
858 ALOGD("%s: %d: napb: disabling native mode in hardware",
859 __func__, __LINE__);
860 audio_route_reset_and_update_path(adev->audio_route,
861 "true-native-mode");
862 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530863 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
864 adev->asrc_mode_enabled) {
865 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
866 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
867 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530868 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530869
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200870 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700871 audio_extn_sound_trigger_update_device_status(snd_device,
872 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530873 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800874 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 return 0;
878}
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530881 struct audio_usecase *uc_info,
882 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883{
884 struct listnode *node;
885 struct audio_usecase *usecase;
886 bool switch_device[AUDIO_USECASE_MAX];
887 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530888 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 /*
890 * This function is to make sure that all the usecases that are active on
891 * the hardware codec backend are always routed to any one device that is
892 * handled by the hardware codec.
893 * For example, if low-latency and deep-buffer usecases are currently active
894 * on speaker and out_set_parameters(headset) is received on low-latency
895 * output, then we have to make sure deep-buffer is also switched to headset,
896 * because of the limitation that both the devices cannot be enabled
897 * at the same time as they share the same backend.
898 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700899 /*
900 * This call is to check if we need to force routing for a particular stream
901 * If there is a backend configuration change for the device when a
902 * new stream starts, then ADM needs to be closed and re-opened with the new
903 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800904 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700905 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800906 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
907 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530908 /* For a2dp device reconfigure all active sessions
909 * with new AFE encoder format based on a2dp state
910 */
911 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 force_restart_session = true;
916 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530917 ALOGD("%s:becf: force routing %d", __func__, force_routing);
918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800921 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 for (i = 0; i < AUDIO_USECASE_MAX; i++)
923 switch_device[i] = false;
924
925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800927
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530928 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
929 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530930 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530931 platform_get_snd_device_name(usecase->out_snd_device),
932 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800933 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530934 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530935 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530936 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
937 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
938 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530939 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
940 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
941 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530942 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
944 platform_get_snd_device_name(usecase->out_snd_device));
945 disable_audio_route(adev, usecase);
946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530951 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
952 num_uc_to_switch);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700955 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530957 /* Make sure the previous devices to be disabled first and then enable the
958 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 }
964 }
965
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700970 }
971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 /* Re-route all the usecases on the shared backend other than the
974 specified usecase to new snd devices */
975 list_for_each(node, &adev->usecase_list) {
976 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530977 /* Update the out_snd_device only before enabling the audio route */
978 if (switch_device[usecase->id]) {
979 usecase->out_snd_device = snd_device;
980 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530981 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530982 use_case_table[usecase->id],
983 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989}
990
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530991static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 struct audio_usecase *uc_info,
993 snd_device_t snd_device)
994{
995 struct listnode *node;
996 struct audio_usecase *usecase;
997 bool switch_device[AUDIO_USECASE_MAX];
998 int i, num_uc_to_switch = 0;
999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301000 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1001 snd_device);
1002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001018 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301020 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001021 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301022 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001023 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001024 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001025 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1026 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001027 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001029 switch_device[usecase->id] = true;
1030 num_uc_to_switch++;
1031 }
1032 }
1033
1034 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001035 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301037 /* Make sure the previous devices to be disabled first and then enable the
1038 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001043 }
1044 }
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001049 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 }
1051 }
1052
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001053 /* Re-route all the usecases on the shared backend other than the
1054 specified usecase to new snd devices */
1055 list_for_each(node, &adev->usecase_list) {
1056 usecase = node_to_item(node, struct audio_usecase, list);
1057 /* Update the in_snd_device only before enabling the audio route */
1058 if (switch_device[usecase->id] ) {
1059 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001060 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301061 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001064 }
1065}
1066
Mingming Yin3a941d42016-02-17 18:08:05 -08001067static void reset_hdmi_sink_caps(struct stream_out *out) {
1068 int i = 0;
1069
1070 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1071 out->supported_channel_masks[i] = 0;
1072 }
1073 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1074 out->supported_formats[i] = 0;
1075 }
1076 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1077 out->supported_sample_rates[i] = 0;
1078 }
1079}
1080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001082static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083{
Mingming Yin3a941d42016-02-17 18:08:05 -08001084 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001085 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Mingming Yin3a941d42016-02-17 18:08:05 -08001087 reset_hdmi_sink_caps(out);
1088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001091 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001092 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001093 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1094 case 6:
1095 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1096 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1097 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1098 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 break;
1102 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001103 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001104 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 break;
1106 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001107
1108 // check channel format caps
1109 i = 0;
1110 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1111 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1112 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1113 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1114 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1115 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1116 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1117 }
1118
1119 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1120 ALOGV(":%s HDMI supports DTS format", __func__);
1121 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1122 }
1123
1124 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1125 ALOGV(":%s HDMI supports DTS HD format", __func__);
1126 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1127 }
1128
1129
1130 // check sample rate caps
1131 i = 0;
1132 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1133 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1134 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1135 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1136 }
1137 }
1138
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001139 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140}
1141
Alexy Josephb1379942016-01-29 15:49:38 -08001142audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001143 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001144{
1145 struct audio_usecase *usecase;
1146 struct listnode *node;
1147
1148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151 ALOGV("%s: usecase id %d", __func__, usecase->id);
1152 return usecase->id;
1153 }
1154 }
1155 return USECASE_INVALID;
1156}
1157
Alexy Josephb1379942016-01-29 15:49:38 -08001158struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001159 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160{
1161 struct audio_usecase *usecase;
1162 struct listnode *node;
1163
1164 list_for_each(node, &adev->usecase_list) {
1165 usecase = node_to_item(node, struct audio_usecase, list);
1166 if (usecase->id == uc_id)
1167 return usecase;
1168 }
1169 return NULL;
1170}
1171
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301172/*
1173 * is a true native playback active
1174 */
1175bool audio_is_true_native_stream_active(struct audio_device *adev)
1176{
1177 bool active = false;
1178 int i = 0;
1179 struct listnode *node;
1180
1181 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1182 ALOGV("%s:napb: not in true mode or non hdphones device",
1183 __func__);
1184 active = false;
1185 goto exit;
1186 }
1187
1188 list_for_each(node, &adev->usecase_list) {
1189 struct audio_usecase *uc;
1190 uc = node_to_item(node, struct audio_usecase, list);
1191 struct stream_out *curr_out =
1192 (struct stream_out*) uc->stream.out;
1193
1194 if (curr_out && PCM_PLAYBACK == uc->type) {
1195 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1196 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1197 uc->id, curr_out->sample_rate,
1198 curr_out->bit_width,
1199 platform_get_snd_device_name(uc->out_snd_device));
1200
1201 if (is_offload_usecase(uc->id) &&
1202 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1203 active = true;
1204 ALOGD("%s:napb:native stream detected", __func__);
1205 }
1206 }
1207 }
1208exit:
1209 return active;
1210}
1211
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301212/*
1213 * if native DSD playback active
1214 */
1215bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1216{
1217 bool active = false;
1218 struct listnode *node = NULL;
1219 struct audio_usecase *uc = NULL;
1220 struct stream_out *curr_out = NULL;
1221
1222 list_for_each(node, &adev->usecase_list) {
1223 uc = node_to_item(node, struct audio_usecase, list);
1224 curr_out = (struct stream_out*) uc->stream.out;
1225
1226 if (curr_out && PCM_PLAYBACK == uc->type &&
1227 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1228 active = true;
1229 ALOGV("%s:DSD playback is active", __func__);
1230 }
1231 }
1232 return active;
1233}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301234
1235static bool force_device_switch(struct audio_usecase *usecase)
1236{
1237 bool ret = false;
1238 bool is_it_true_mode = false;
1239
1240 if (is_offload_usecase(usecase->id) &&
1241 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001242 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1243 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1244 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301245 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1246 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1247 (!is_it_true_mode && adev->native_playback_enabled)){
1248 ret = true;
1249 ALOGD("napb: time to toggle native mode");
1250 }
1251 }
1252
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301253 // Force all a2dp output devices to reconfigure for proper AFE encode format
1254 if((usecase->stream.out) &&
1255 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1256 audio_extn_a2dp_is_force_device_switch()) {
1257 ALOGD("Force a2dp device switch to update new encoder config");
1258 ret = true;
1259 }
1260
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301261 return ret;
1262}
1263
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001264int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001266 snd_device_t out_snd_device = SND_DEVICE_NONE;
1267 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001268 struct audio_usecase *usecase = NULL;
1269 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001270 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001271 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001272 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301275 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 usecase = get_usecase_from_list(adev, uc_id);
1278 if (usecase == NULL) {
1279 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1280 return -EINVAL;
1281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001283 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001284 (usecase->type == VOIP_CALL) ||
1285 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001286 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001287 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001288 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 usecase->devices = usecase->stream.out->devices;
1290 } else {
1291 /*
1292 * If the voice call is active, use the sound devices of voice call usecase
1293 * so that it would not result any device switch. All the usecases will
1294 * be switched to new device when select_devices() is called for voice call
1295 * usecase. This is to avoid switching devices for voice call when
1296 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001297 * choose voice call device only if the use case device is
1298 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001300 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001301 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001302 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001303 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1304 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301305 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1306 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001307 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 in_snd_device = vc_usecase->in_snd_device;
1309 out_snd_device = vc_usecase->out_snd_device;
1310 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001311 } else if (voice_extn_compress_voip_is_active(adev)) {
1312 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001313 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001314 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1315 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001316 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001317 in_snd_device = voip_usecase->in_snd_device;
1318 out_snd_device = voip_usecase->out_snd_device;
1319 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001320 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001321 hfp_ucid = audio_extn_hfp_get_usecase();
1322 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001323 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001324 in_snd_device = hfp_usecase->in_snd_device;
1325 out_snd_device = hfp_usecase->out_snd_device;
1326 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 }
1328 if (usecase->type == PCM_PLAYBACK) {
1329 usecase->devices = usecase->stream.out->devices;
1330 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001331 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001332 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001333 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001334 if (usecase->stream.out == adev->primary_output &&
1335 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001336 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001337 select_devices(adev, adev->active_input->usecase);
1338 }
1339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 } else if (usecase->type == PCM_CAPTURE) {
1341 usecase->devices = usecase->stream.in->device;
1342 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001343 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001344 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001345 if (adev->active_input &&
1346 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301347 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1348 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1349 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001350 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001351 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001352 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1353 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001354 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001355 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001356 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 }
1358 }
1359
1360 if (out_snd_device == usecase->out_snd_device &&
1361 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301362
1363 if (!force_device_switch(usecase))
1364 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365 }
1366
sangwoobc677242013-08-08 16:53:43 +09001367 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001368 out_snd_device, platform_get_snd_device_name(out_snd_device),
1369 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371 /*
1372 * Limitation: While in call, to do a device switch we need to disable
1373 * and enable both RX and TX devices though one of them is same as current
1374 * device.
1375 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001376 if ((usecase->type == VOICE_CALL) &&
1377 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1378 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001379 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001380 }
1381
1382 if (((usecase->type == VOICE_CALL) ||
1383 (usecase->type == VOIP_CALL)) &&
1384 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1385 /* Disable sidetone only if voice/voip call already exists */
1386 if (voice_is_call_state_active(adev) ||
1387 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001388 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001389 }
1390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 /* Disable current sound devices */
1392 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001393 disable_audio_route(adev, usecase);
1394 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395 }
1396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001398 disable_audio_route(adev, usecase);
1399 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 }
1401
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001402 /* Applicable only on the targets that has external modem.
1403 * New device information should be sent to modem before enabling
1404 * the devices to reduce in-call device switch time.
1405 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001406 if ((usecase->type == VOICE_CALL) &&
1407 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1408 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001409 status = platform_switch_voice_call_enable_device_config(adev->platform,
1410 out_snd_device,
1411 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001412 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 /* Enable new sound devices */
1415 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001416 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001417 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418 }
1419
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001420 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301421 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001423 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424
Avinash Vaish71a8b972014-07-24 15:36:33 +05301425 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001426 status = platform_switch_voice_call_device_post(adev->platform,
1427 out_snd_device,
1428 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301429 enable_audio_route_for_voice_usecases(adev, usecase);
1430 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001431
sangwoo170731f2013-06-08 15:36:36 +09001432 usecase->in_snd_device = in_snd_device;
1433 usecase->out_snd_device = out_snd_device;
1434
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301435 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001436 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301437 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001438 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301439 usecase->stream.out->flags,
1440 usecase->stream.out->format,
1441 usecase->stream.out->sample_rate,
1442 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301443 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301444 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001445 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301446 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001447
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001449
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001450 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1451 /* Enable sidetone only if other voice/voip call already exists */
1452 if (voice_is_call_state_active(adev) ||
1453 voice_extn_compress_voip_is_started(adev))
1454 voice_set_sidetone(adev, out_snd_device, true);
1455 }
1456
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001457 /* Applicable only on the targets that has external modem.
1458 * Enable device command should be sent to modem only after
1459 * enabling voice call mixer controls
1460 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001461 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001462 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1463 out_snd_device,
1464 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301465 ALOGD("%s: done",__func__);
1466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 return status;
1468}
1469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470static int stop_input_stream(struct stream_in *in)
1471{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301472 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 struct audio_usecase *uc_info;
1474 struct audio_device *adev = in->dev;
1475
Eric Laurentc8400632013-02-14 19:04:54 -08001476 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Eric Laurent994a6932013-07-17 11:51:42 -07001478 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 uc_info = get_usecase_from_list(adev, in->usecase);
1481 if (uc_info == NULL) {
1482 ALOGE("%s: Could not find the usecase (%d) in the list",
1483 __func__, in->usecase);
1484 return -EINVAL;
1485 }
1486
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001487 /* Close in-call recording streams */
1488 voice_check_and_stop_incall_rec_usecase(adev, in);
1489
Eric Laurent150dbfe2013-02-27 14:31:02 -08001490 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492
1493 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001494 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001496 list_remove(&uc_info->list);
1497 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498
Eric Laurent994a6932013-07-17 11:51:42 -07001499 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500 return ret;
1501}
1502
1503int start_input_stream(struct stream_in *in)
1504{
1505 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001506 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 struct audio_usecase *uc_info;
1508 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301509 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510
Mingming Yin2664a5b2015-09-03 10:53:11 -07001511 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1512 if (get_usecase_from_list(adev, usecase) == NULL)
1513 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301514 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1515 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001516
Naresh Tanniru80659832014-06-04 18:17:56 +05301517
1518 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301519 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301520 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301521 goto error_config;
1522 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301523
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001524 /* Check if source matches incall recording usecase criteria */
1525 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1526 if (ret)
1527 goto error_config;
1528 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001529 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1530
1531 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1532 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1533 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001534 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001535 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001536
Eric Laurentb23d5282013-05-14 15:27:20 -07001537 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 if (in->pcm_device_id < 0) {
1539 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1540 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001541 ret = -EINVAL;
1542 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544
1545 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001547
1548 if (!uc_info) {
1549 ret = -ENOMEM;
1550 goto error_config;
1551 }
1552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 uc_info->id = in->usecase;
1554 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001555 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 uc_info->devices = in->device;
1557 uc_info->in_snd_device = SND_DEVICE_NONE;
1558 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001560 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301561 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1562 adev->perf_lock_opts,
1563 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301566 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1567 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001568
1569 unsigned int flags = PCM_IN;
1570 unsigned int pcm_open_retry_count = 0;
1571
1572 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1573 flags |= PCM_MMAP | PCM_NOIRQ;
1574 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001575 } else if (in->realtime) {
1576 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001577 }
1578
1579 while (1) {
1580 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1581 flags, &in->config);
1582 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1583 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1584 if (in->pcm != NULL) {
1585 pcm_close(in->pcm);
1586 in->pcm = NULL;
1587 }
1588 if (pcm_open_retry_count-- == 0) {
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1593 continue;
1594 }
1595 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001597
1598 ALOGV("%s: pcm_prepare", __func__);
1599 ret = pcm_prepare(in->pcm);
1600 if (ret < 0) {
1601 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1602 pcm_close(in->pcm);
1603 in->pcm = NULL;
1604 goto error_open;
1605 }
1606
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001607 register_in_stream(in);
1608 if (in->realtime) {
1609 ret = pcm_start(in->pcm);
1610 if (ret < 0)
1611 goto error_open;
1612 }
1613
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301614 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001615 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001616
Eric Laurentc8400632013-02-14 19:04:54 -08001617 return ret;
1618
1619error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301620 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001622error_config:
1623 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301624 /*
1625 * sleep 50ms to allow sufficient time for kernel
1626 * drivers to recover incases like SSR.
1627 */
1628 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001630
1631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632}
1633
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001634void lock_input_stream(struct stream_in *in)
1635{
1636 pthread_mutex_lock(&in->pre_lock);
1637 pthread_mutex_lock(&in->lock);
1638 pthread_mutex_unlock(&in->pre_lock);
1639}
1640
1641void lock_output_stream(struct stream_out *out)
1642{
1643 pthread_mutex_lock(&out->pre_lock);
1644 pthread_mutex_lock(&out->lock);
1645 pthread_mutex_unlock(&out->pre_lock);
1646}
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648/* must be called with out->lock locked */
1649static int send_offload_cmd_l(struct stream_out* out, int command)
1650{
1651 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1652
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001653 if (!cmd) {
1654 ALOGE("failed to allocate mem for command 0x%x", command);
1655 return -ENOMEM;
1656 }
1657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 ALOGVV("%s %d", __func__, command);
1659
1660 cmd->cmd = command;
1661 list_add_tail(&out->offload_cmd_list, &cmd->node);
1662 pthread_cond_signal(&out->offload_cond);
1663 return 0;
1664}
1665
1666/* must be called iwth out->lock locked */
1667static void stop_compressed_output_l(struct stream_out *out)
1668{
1669 out->offload_state = OFFLOAD_STATE_IDLE;
1670 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001671 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672 if (out->compr != NULL) {
1673 compress_stop(out->compr);
1674 while (out->offload_thread_blocked) {
1675 pthread_cond_wait(&out->cond, &out->lock);
1676 }
1677 }
1678}
1679
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001680bool is_offload_usecase(audio_usecase_t uc_id)
1681{
1682 unsigned int i;
1683 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1684 if (uc_id == offload_usecases[i])
1685 return true;
1686 }
1687 return false;
1688}
1689
vivek mehta446c3962015-09-14 10:57:35 -07001690static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001691{
vivek mehta446c3962015-09-14 10:57:35 -07001692 audio_usecase_t ret_uc = USECASE_INVALID;
1693 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001694 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001695 if (!adev->multi_offload_enable) {
1696 if (is_direct_pcm)
1697 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1698 else
1699 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001700
vivek mehta446c3962015-09-14 10:57:35 -07001701 pthread_mutex_lock(&adev->lock);
1702 if (get_usecase_from_list(adev, ret_uc) != NULL)
1703 ret_uc = USECASE_INVALID;
1704 pthread_mutex_unlock(&adev->lock);
1705
1706 return ret_uc;
1707 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001708
1709 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001710 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1711 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1712 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1713 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001714 break;
1715 }
1716 }
vivek mehta446c3962015-09-14 10:57:35 -07001717
1718 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1719 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001720}
1721
1722static void free_offload_usecase(struct audio_device *adev,
1723 audio_usecase_t uc_id)
1724{
vivek mehta446c3962015-09-14 10:57:35 -07001725 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001726 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001727
1728 if (!adev->multi_offload_enable)
1729 return;
1730
1731 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1732 if (offload_usecases[offload_uc_index] == uc_id) {
1733 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001734 break;
1735 }
1736 }
1737 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1738}
1739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740static void *offload_thread_loop(void *context)
1741{
1742 struct stream_out *out = (struct stream_out *) context;
1743 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001744 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1747 set_sched_policy(0, SP_FOREGROUND);
1748 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1749
1750 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001751 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 for (;;) {
1753 struct offload_cmd *cmd = NULL;
1754 stream_callback_event_t event;
1755 bool send_callback = false;
1756
1757 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1758 __func__, list_empty(&out->offload_cmd_list),
1759 out->offload_state);
1760 if (list_empty(&out->offload_cmd_list)) {
1761 ALOGV("%s SLEEPING", __func__);
1762 pthread_cond_wait(&out->offload_cond, &out->lock);
1763 ALOGV("%s RUNNING", __func__);
1764 continue;
1765 }
1766
1767 item = list_head(&out->offload_cmd_list);
1768 cmd = node_to_item(item, struct offload_cmd, node);
1769 list_remove(item);
1770
1771 ALOGVV("%s STATE %d CMD %d out->compr %p",
1772 __func__, out->offload_state, cmd->cmd, out->compr);
1773
1774 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1775 free(cmd);
1776 break;
1777 }
1778
1779 if (out->compr == NULL) {
1780 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001781 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 pthread_cond_signal(&out->cond);
1783 continue;
1784 }
1785 out->offload_thread_blocked = true;
1786 pthread_mutex_unlock(&out->lock);
1787 send_callback = false;
1788 switch(cmd->cmd) {
1789 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001790 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001792 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 send_callback = true;
1794 event = STREAM_CBK_EVENT_WRITE_READY;
1795 break;
1796 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001797 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301798 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001799 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301800 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001801 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301802 if (ret < 0)
1803 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301804 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301805 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001806 compress_drain(out->compr);
1807 else
1808 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301809 if (ret != -ENETRESET) {
1810 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301811 pthread_mutex_lock(&out->lock);
1812 out->send_new_metadata = 1;
1813 out->send_next_track_params = true;
1814 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301815 event = STREAM_CBK_EVENT_DRAIN_READY;
1816 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1817 } else
1818 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 break;
1820 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001821 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001823 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 send_callback = true;
1825 event = STREAM_CBK_EVENT_DRAIN_READY;
1826 break;
1827 default:
1828 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1829 break;
1830 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001831 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832 out->offload_thread_blocked = false;
1833 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001834 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001835 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001837 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838 free(cmd);
1839 }
1840
1841 pthread_cond_signal(&out->cond);
1842 while (!list_empty(&out->offload_cmd_list)) {
1843 item = list_head(&out->offload_cmd_list);
1844 list_remove(item);
1845 free(node_to_item(item, struct offload_cmd, node));
1846 }
1847 pthread_mutex_unlock(&out->lock);
1848
1849 return NULL;
1850}
1851
1852static int create_offload_callback_thread(struct stream_out *out)
1853{
1854 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1855 list_init(&out->offload_cmd_list);
1856 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1857 offload_thread_loop, out);
1858 return 0;
1859}
1860
1861static int destroy_offload_callback_thread(struct stream_out *out)
1862{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 stop_compressed_output_l(out);
1865 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1866
1867 pthread_mutex_unlock(&out->lock);
1868 pthread_join(out->offload_thread, (void **) NULL);
1869 pthread_cond_destroy(&out->offload_cond);
1870
1871 return 0;
1872}
1873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874static int stop_output_stream(struct stream_out *out)
1875{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301876 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 struct audio_usecase *uc_info;
1878 struct audio_device *adev = out->dev;
1879
Eric Laurent994a6932013-07-17 11:51:42 -07001880 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 uc_info = get_usecase_from_list(adev, out->usecase);
1883 if (uc_info == NULL) {
1884 ALOGE("%s: Could not find the usecase (%d) in the list",
1885 __func__, out->usecase);
1886 return -EINVAL;
1887 }
1888
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001889 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301890 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001891 if (adev->visualizer_stop_output != NULL)
1892 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001893
1894 audio_extn_dts_remove_state_notifier_node(out->usecase);
1895
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001896 if (adev->offload_effects_stop_output != NULL)
1897 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1898 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001899
Eric Laurent150dbfe2013-02-27 14:31:02 -08001900 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001901 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001902
1903 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001904 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001906 list_remove(&uc_info->list);
1907 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001909 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301910 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001911 ALOGV("Disable passthrough , reset mixer to pcm");
1912 /* NO_PASSTHROUGH */
1913 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001914 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001915 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1916 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001917
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301918 /* Must be called after removing the usecase from list */
1919 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301920 audio_extn_keep_alive_start();
1921
Eric Laurent994a6932013-07-17 11:51:42 -07001922 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 return ret;
1924}
1925
1926int start_output_stream(struct stream_out *out)
1927{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 struct audio_usecase *uc_info;
1930 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301931 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001933 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1934 ret = -EINVAL;
1935 goto error_config;
1936 }
1937
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301938 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1939 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1940 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301941
Naresh Tanniru80659832014-06-04 18:17:56 +05301942 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301943 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301944 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301945 goto error_config;
1946 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301947
Eric Laurentb23d5282013-05-14 15:27:20 -07001948 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 if (out->pcm_device_id < 0) {
1950 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1951 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001952 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001953 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 }
1955
1956 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001957
1958 if (!uc_info) {
1959 ret = -ENOMEM;
1960 goto error_config;
1961 }
1962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 uc_info->id = out->usecase;
1964 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001965 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 uc_info->devices = out->devices;
1967 uc_info->in_snd_device = SND_DEVICE_NONE;
1968 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001969 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301971 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1972 adev->perf_lock_opts,
1973 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301974
1975 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1976 audio_extn_keep_alive_stop();
1977 if (audio_extn_passthru_is_enabled() &&
1978 audio_extn_passthru_is_passthrough_stream(out)) {
1979 audio_extn_passthru_on_start(out);
1980 audio_extn_passthru_update_stream_configuration(adev, out);
1981 }
1982 }
1983
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 select_devices(adev, out->usecase);
1985
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001986 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1987 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001988 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001989 unsigned int flags = PCM_OUT;
1990 unsigned int pcm_open_retry_count = 0;
1991 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1992 flags |= PCM_MMAP | PCM_NOIRQ;
1993 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001994 } else if (out->realtime) {
1995 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001996 } else
1997 flags |= PCM_MONOTONIC;
1998
1999 while (1) {
2000 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2001 flags, &out->config);
2002 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2003 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2004 if (out->pcm != NULL) {
2005 pcm_close(out->pcm);
2006 out->pcm = NULL;
2007 }
2008 if (pcm_open_retry_count-- == 0) {
2009 ret = -EIO;
2010 goto error_open;
2011 }
2012 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2013 continue;
2014 }
2015 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002017
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002018 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2019 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002020
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002021 ALOGV("%s: pcm_prepare", __func__);
2022 if (pcm_is_ready(out->pcm)) {
2023 ret = pcm_prepare(out->pcm);
2024 if (ret < 0) {
2025 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2026 pcm_close(out->pcm);
2027 out->pcm = NULL;
2028 goto error_open;
2029 }
2030 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2033 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002035 out->compr = compress_open(adev->snd_card,
2036 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 COMPRESS_IN, &out->compr_config);
2038 if (out->compr && !is_compress_ready(out->compr)) {
2039 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2040 compress_close(out->compr);
2041 out->compr = NULL;
2042 ret = -EIO;
2043 goto error_open;
2044 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302045 /* compress_open sends params of the track, so reset the flag here */
2046 out->is_compr_metadata_avail = false;
2047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 if (out->offload_callback)
2049 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002050
Fred Oh3f43e742015-03-04 18:42:34 -08002051 /* Since small bufs uses blocking writes, a write will be blocked
2052 for the default max poll time (20s) in the event of an SSR.
2053 Reduce the poll time to observe and deal with SSR faster.
2054 */
Ashish Jain5106d362016-05-11 19:23:33 +05302055 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002056 compress_set_max_poll_wait(out->compr, 1000);
2057 }
2058
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002059 audio_extn_dts_create_state_notifier_node(out->usecase);
2060 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2061 popcount(out->channel_mask),
2062 out->playback_started);
2063
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002064#ifdef DS1_DOLBY_DDP_ENABLED
2065 if (audio_extn_is_dolby_format(out->format))
2066 audio_extn_dolby_send_ddp_endp_params(adev);
2067#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302068 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002069 if (adev->visualizer_start_output != NULL)
2070 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2071 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302072 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002073 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002076
2077 if (ret == 0) {
2078 register_out_stream(out);
2079 if (out->realtime) {
2080 ret = pcm_start(out->pcm);
2081 if (ret < 0)
2082 goto error_open;
2083 }
2084 }
2085
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302086 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002087 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002088
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002089 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302091 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002093error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302094 /*
2095 * sleep 50ms to allow sufficient time for kernel
2096 * drivers to recover incases like SSR.
2097 */
2098 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002099 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100}
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102static int check_input_parameters(uint32_t sample_rate,
2103 audio_format_t format,
2104 int channel_count)
2105{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002106 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302108 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2109 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2110 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002111 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302112 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002113
2114 switch (channel_count) {
2115 case 1:
2116 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302117 case 3:
2118 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002119 case 6:
2120 break;
2121 default:
2122 ret = -EINVAL;
2123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
2125 switch (sample_rate) {
2126 case 8000:
2127 case 11025:
2128 case 12000:
2129 case 16000:
2130 case 22050:
2131 case 24000:
2132 case 32000:
2133 case 44100:
2134 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302135 case 96000:
2136 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 break;
2138 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002139 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 }
2141
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002142 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143}
2144
2145static size_t get_input_buffer_size(uint32_t sample_rate,
2146 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002147 int channel_count,
2148 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149{
2150 size_t size = 0;
2151
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002152 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2153 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002155 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002156 if (is_low_latency)
2157 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302158
2159 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002161 /* make sure the size is multiple of 32 bytes
2162 * At 48 kHz mono 16-bit PCM:
2163 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2164 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2165 */
2166 size += 0x1f;
2167 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002168
2169 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170}
2171
Ashish Jain5106d362016-05-11 19:23:33 +05302172static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2173{
2174 uint64_t actual_frames_rendered = 0;
2175 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2176
2177 /* This adjustment accounts for buffering after app processor.
2178 * It is based on estimated DSP latency per use case, rather than exact.
2179 */
2180 int64_t platform_latency = platform_render_latency(out->usecase) *
2181 out->sample_rate / 1000000LL;
2182
2183 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2184 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2185 * hence only estimate.
2186 */
2187 int64_t signed_frames = out->written - kernel_buffer_size;
2188
2189 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2190
2191 if (signed_frames > 0)
2192 actual_frames_rendered = signed_frames;
2193
2194 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2195 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2196 (long long int)out->written, (int)kernel_buffer_size,
2197 audio_bytes_per_sample(out->compr_config.codec->format),
2198 popcount(out->channel_mask));
2199
2200 return actual_frames_rendered;
2201}
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2204{
2205 struct stream_out *out = (struct stream_out *)stream;
2206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002210static int out_set_sample_rate(struct audio_stream *stream __unused,
2211 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212{
2213 return -ENOSYS;
2214}
2215
2216static size_t out_get_buffer_size(const struct audio_stream *stream)
2217{
2218 struct stream_out *out = (struct stream_out *)stream;
2219
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002220 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002222 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2223 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302224 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302225 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002227 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002228 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
2231static uint32_t out_get_channels(const struct audio_stream *stream)
2232{
2233 struct stream_out *out = (struct stream_out *)stream;
2234
2235 return out->channel_mask;
2236}
2237
2238static audio_format_t out_get_format(const struct audio_stream *stream)
2239{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 struct stream_out *out = (struct stream_out *)stream;
2241
2242 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243}
2244
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002245static int out_set_format(struct audio_stream *stream __unused,
2246 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247{
2248 return -ENOSYS;
2249}
2250
2251static int out_standby(struct audio_stream *stream)
2252{
2253 struct stream_out *out = (struct stream_out *)stream;
2254 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302256 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2257 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002259 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002261 if (adev->adm_deregister_stream)
2262 adev->adm_deregister_stream(adev->adm_data, out->handle);
2263
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002264 if (is_offload_usecase(out->usecase))
2265 stop_compressed_output_l(out);
2266
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002267 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002269 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2270 voice_extn_compress_voip_close_output_stream(stream);
2271 pthread_mutex_unlock(&adev->lock);
2272 pthread_mutex_unlock(&out->lock);
2273 ALOGD("VOIP output entered standby");
2274 return 0;
2275 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 if (out->pcm) {
2277 pcm_close(out->pcm);
2278 out->pcm = NULL;
2279 }
2280 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002281 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302282 out->send_next_track_params = false;
2283 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002284 out->gapless_mdata.encoder_delay = 0;
2285 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 if (out->compr != NULL) {
2287 compress_close(out->compr);
2288 out->compr = NULL;
2289 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002292 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 }
2294 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302295 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 return 0;
2297}
2298
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002299static int out_dump(const struct audio_stream *stream __unused,
2300 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301{
2302 return 0;
2303}
2304
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002305static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2306{
2307 int ret = 0;
2308 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002309
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002310 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002311 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002312 return -EINVAL;
2313 }
2314
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302315 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002316
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002317 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2318 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302319 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002320 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002321 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2322 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302323 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002324 }
2325
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326 ALOGV("%s new encoder delay %u and padding %u", __func__,
2327 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2328
2329 return 0;
2330}
2331
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002332static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2333{
2334 return out == adev->primary_output || out == adev->voice_tx_output;
2335}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340 struct audio_device *adev = out->dev;
2341 struct str_parms *parms;
2342 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002343 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
sangwoobc677242013-08-08 16:53:43 +09002345 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002346 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302348 if (!parms)
2349 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002350 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2351 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002353 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002354 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002356 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002357 * When HDMI cable is unplugged the music playback is paused and
2358 * the policy manager sends routing=0. But the audioflinger continues
2359 * to write data until standby time (3sec). As the HDMI core is
2360 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002361 * Avoid this by routing audio to speaker until standby.
2362 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002363 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2364 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302365 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002366 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2367 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002368 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302369 /*
2370 * When A2DP is disconnected the
2371 * music playback is paused and the policy manager sends routing=0
2372 * But the audioflingercontinues to write data until standby time
2373 * (3sec). As BT is turned off, the write gets blocked.
2374 * Avoid this by routing audio to speaker until standby.
2375 */
2376 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2377 (val == AUDIO_DEVICE_NONE)) {
2378 val = AUDIO_DEVICE_OUT_SPEAKER;
2379 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002380
2381 /*
2382 * select_devices() call below switches all the usecases on the same
2383 * backend to the new device. Refer to check_usecases_codec_backend() in
2384 * the select_devices(). But how do we undo this?
2385 *
2386 * For example, music playback is active on headset (deep-buffer usecase)
2387 * and if we go to ringtones and select a ringtone, low-latency usecase
2388 * will be started on headset+speaker. As we can't enable headset+speaker
2389 * and headset devices at the same time, select_devices() switches the music
2390 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2391 * So when the ringtone playback is completed, how do we undo the same?
2392 *
2393 * We are relying on the out_set_parameters() call on deep-buffer output,
2394 * once the ringtone playback is ended.
2395 * NOTE: We should not check if the current devices are same as new devices.
2396 * Because select_devices() must be called to switch back the music
2397 * playback to headset.
2398 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002399 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002400 audio_devices_t new_dev = val;
2401 bool same_dev = out->devices == new_dev;
2402 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002403
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002404 if (output_drives_call(adev, out)) {
2405 if(!voice_is_in_call(adev)) {
2406 if (adev->mode == AUDIO_MODE_IN_CALL) {
2407 adev->current_call_output = out;
2408 ret = voice_start_call(adev);
2409 }
2410 } else {
2411 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002412 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002413 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002414 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002415
2416 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002417 if (!same_dev) {
2418 ALOGV("update routing change");
2419 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302420 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2421 adev->perf_lock_opts,
2422 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002423 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002424 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302425 if (!same_dev)
2426 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002427 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002428 }
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002431 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002433
2434 if (out == adev->primary_output) {
2435 pthread_mutex_lock(&adev->lock);
2436 audio_extn_set_parameters(adev, parms);
2437 pthread_mutex_unlock(&adev->lock);
2438 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002439 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002440 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002441 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002442
2443 audio_extn_dts_create_state_notifier_node(out->usecase);
2444 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2445 popcount(out->channel_mask),
2446 out->playback_started);
2447
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002448 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002449 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302452error:
Eric Laurent994a6932013-07-17 11:51:42 -07002453 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454 return ret;
2455}
2456
2457static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2458{
2459 struct stream_out *out = (struct stream_out *)stream;
2460 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002461 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 char value[256];
2463 struct str_parms *reply = str_parms_create();
2464 size_t i, j;
2465 int ret;
2466 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002467
2468 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002469 if (reply) {
2470 str_parms_destroy(reply);
2471 }
2472 if (query) {
2473 str_parms_destroy(query);
2474 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002475 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2476 return NULL;
2477 }
2478
Eric Laurent994a6932013-07-17 11:51:42 -07002479 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2481 if (ret >= 0) {
2482 value[0] = '\0';
2483 i = 0;
2484 while (out->supported_channel_masks[i] != 0) {
2485 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2486 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2487 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002488 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002490 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 first = false;
2492 break;
2493 }
2494 }
2495 i++;
2496 }
2497 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2498 str = str_parms_to_str(reply);
2499 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002500 voice_extn_out_get_parameters(out, query, reply);
2501 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002502 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002503 free(str);
2504 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002507
Alexy Joseph62142aa2015-11-16 15:10:34 -08002508
2509 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2510 if (ret >= 0) {
2511 value[0] = '\0';
2512 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2513 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302514 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002515 } else {
2516 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302517 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002518 }
2519 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002520 if (str)
2521 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002522 str = str_parms_to_str(reply);
2523 }
2524
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002525 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2526 if (ret >= 0) {
2527 value[0] = '\0';
2528 i = 0;
2529 first = true;
2530 while (out->supported_formats[i] != 0) {
2531 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2532 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2533 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002534 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002535 }
2536 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2537 first = false;
2538 break;
2539 }
2540 }
2541 i++;
2542 }
2543 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002544 if (str)
2545 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002546 str = str_parms_to_str(reply);
2547 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002548
2549 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2550 if (ret >= 0) {
2551 value[0] = '\0';
2552 i = 0;
2553 first = true;
2554 while (out->supported_sample_rates[i] != 0) {
2555 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2556 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2557 if (!first) {
2558 strlcat(value, "|", sizeof(value));
2559 }
2560 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2561 first = false;
2562 break;
2563 }
2564 }
2565 i++;
2566 }
2567 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2568 if (str)
2569 free(str);
2570 str = str_parms_to_str(reply);
2571 }
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 str_parms_destroy(query);
2574 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002575 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 return str;
2577}
2578
2579static uint32_t out_get_latency(const struct audio_stream_out *stream)
2580{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002581 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002583 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Alexy Josephaa54c872014-12-03 02:46:47 -08002585 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002586 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002587 } else if (out->realtime) {
2588 // since the buffer won't be filled up faster than realtime,
2589 // return a smaller number
2590 if (out->config.rate)
2591 period_ms = (out->af_period_multiplier * out->config.period_size *
2592 1000) / (out->config.rate);
2593 else
2594 period_ms = 0;
2595 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002596 } else {
2597 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002599 }
2600
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302601 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002602 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603}
2604
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302605static float AmpToDb(float amplification)
2606{
2607 if (amplification == 0) {
2608 return DSD_VOLUME_MIN_DB;
2609 }
2610 return 20 * log10(amplification);
2611}
2612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613static int out_set_volume(struct audio_stream_out *stream, float left,
2614 float right)
2615{
Eric Laurenta9024de2013-04-04 09:19:12 -07002616 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 int volume[2];
2618
Eric Laurenta9024de2013-04-04 09:19:12 -07002619 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2620 /* only take left channel into account: the API is for stereo anyway */
2621 out->muted = (left == 0.0f);
2622 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002623 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302624 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002625 /*
2626 * Set mute or umute on HDMI passthrough stream.
2627 * Only take left channel into account.
2628 * Mute is 0 and unmute 1
2629 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302630 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302631 } else if (out->format == AUDIO_FORMAT_DSD){
2632 char mixer_ctl_name[128] = "DSD Volume";
2633 struct audio_device *adev = out->dev;
2634 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2635
2636 if (!ctl) {
2637 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2638 __func__, mixer_ctl_name);
2639 return -EINVAL;
2640 }
2641 volume[0] = (int)(AmpToDb(left));
2642 volume[1] = (int)(AmpToDb(right));
2643 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2644 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002645 } else {
2646 char mixer_ctl_name[128];
2647 struct audio_device *adev = out->dev;
2648 struct mixer_ctl *ctl;
2649 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002650 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002651
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002652 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2653 "Compress Playback %d Volume", pcm_device_id);
2654 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2655 if (!ctl) {
2656 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2657 __func__, mixer_ctl_name);
2658 return -EINVAL;
2659 }
2660 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2661 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2662 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2663 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002665 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 return -ENOSYS;
2668}
2669
2670static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2671 size_t bytes)
2672{
2673 struct stream_out *out = (struct stream_out *)stream;
2674 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302675 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002676 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002678 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302679
Naresh Tanniru80659832014-06-04 18:17:56 +05302680 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002681
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302682 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302683 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302684 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2685 pthread_mutex_unlock(&out->lock);
2686 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302687 } else {
2688 /* increase written size during SSR to avoid mismatch
2689 * with the written frames count in AF
2690 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302691 if (audio_bytes_per_sample(out->format) != 0)
2692 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302693 ALOGD(" %s: sound card is not active/SSR state", __func__);
2694 ret= -EIO;
2695 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302696 }
2697 }
2698
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302699 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302700 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2701 if (audio_bytes_per_sample(out->format) != 0)
2702 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2703 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302704 goto exit;
2705 }
2706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002708 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002709 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002710 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2711 ret = voice_extn_compress_voip_start_output_stream(out);
2712 else
2713 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002714 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002717 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 goto exit;
2719 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002720
2721 if (last_known_cal_step != -1) {
2722 ALOGD("%s: retry previous failed cal level set", __func__);
2723 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726
Ashish Jain81eb2a82015-05-13 10:52:34 +05302727 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002728 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302729 adev->is_channel_status_set = true;
2730 }
2731
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002732 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002733 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002734 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002735 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002736 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2737 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302738 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2739 ALOGD("copl(%p):send next track params in gapless", out);
2740 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2741 out->send_next_track_params = false;
2742 out->is_compr_metadata_avail = false;
2743 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002744 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302745 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302746 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002747
Ashish Jain83a6cc22016-06-28 14:34:17 +05302748 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302749 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302750 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302751 pthread_mutex_unlock(&out->lock);
2752 return -EINVAL;
2753 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302754 audio_format_t dst_format = out->hal_op_format;
2755 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302756
2757 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2758 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2759
Ashish Jain83a6cc22016-06-28 14:34:17 +05302760 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302761 dst_format,
2762 buffer,
2763 src_format,
2764 frames);
2765
Ashish Jain83a6cc22016-06-28 14:34:17 +05302766 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302767 bytes_to_write);
2768
2769 /*Convert written bytes in audio flinger format*/
2770 if (ret > 0)
2771 ret = ((ret * format_to_bitwidth_table[out->format]) /
2772 format_to_bitwidth_table[dst_format]);
2773 }
2774 } else
2775 ret = compress_write(out->compr, buffer, bytes);
2776
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302777 if (ret < 0)
2778 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302779 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002780 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302781 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002782 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302783 } else if (-ENETRESET == ret) {
2784 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2785 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2786 pthread_mutex_unlock(&out->lock);
2787 out_standby(&out->stream.common);
2788 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 }
Ashish Jain5106d362016-05-11 19:23:33 +05302790 if ( ret == (ssize_t)bytes && !out->non_blocking)
2791 out->written += bytes;
2792
Naresh Tanniru80659832014-06-04 18:17:56 +05302793 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002795 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002796 out->playback_started = 1;
2797 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002798
2799 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2800 popcount(out->channel_mask),
2801 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002802 }
2803 pthread_mutex_unlock(&out->lock);
2804 return ret;
2805 } else {
2806 if (out->pcm) {
2807 if (out->muted)
2808 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002809
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302810 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002811
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002812 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002813
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002814 if (out->config.rate)
2815 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2816 out->config.rate;
2817
2818 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2819
2820 request_out_focus(out, ns);
2821
2822 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002823 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002824 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302825 out->convert_buffer != NULL) {
2826
2827 memcpy_by_audio_format(out->convert_buffer,
2828 out->hal_op_format,
2829 buffer,
2830 out->hal_ip_format,
2831 out->config.period_size * out->config.channels);
2832
2833 ret = pcm_write(out->pcm, out->convert_buffer,
2834 (out->config.period_size *
2835 out->config.channels *
2836 format_to_bitwidth_table[out->hal_op_format]));
2837 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002838 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302839 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002840
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002841 release_out_focus(out);
2842
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302843 if (ret < 0)
2844 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302845 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2846 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2847 else
2848 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 }
2851
2852exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302853 /* ToDo: There may be a corner case when SSR happens back to back during
2854 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302855 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302856 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302857 }
2858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 pthread_mutex_unlock(&out->lock);
2860
2861 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002862 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002863 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302864 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302865 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302866 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302867 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302868 out->standby = true;
2869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302871 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302872 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 }
2874 return bytes;
2875}
2876
2877static int out_get_render_position(const struct audio_stream_out *stream,
2878 uint32_t *dsp_frames)
2879{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302881 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002882
2883 if (dsp_frames == NULL)
2884 return -EINVAL;
2885
2886 *dsp_frames = 0;
2887 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002888 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302889
2890 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2891 * this operation and adev_close_output_stream(where out gets reset).
2892 */
2893 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2894 *dsp_frames = get_actual_pcm_frames_rendered(out);
2895 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2896 return 0;
2897 }
2898
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002899 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302900 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302901 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302903 if (ret < 0)
2904 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302906 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 }
2908 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302909 if (-ENETRESET == ret) {
2910 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2911 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2912 return -EINVAL;
2913 } else if(ret < 0) {
2914 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2915 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302916 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2917 /*
2918 * Handle corner case where compress session is closed during SSR
2919 * and timestamp is queried
2920 */
2921 ALOGE(" ERROR: sound card not active, return error");
2922 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302923 } else {
2924 return 0;
2925 }
Zhou Song32a556e2015-05-05 10:46:56 +08002926 } else if (audio_is_linear_pcm(out->format)) {
2927 *dsp_frames = out->written;
2928 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 } else
2930 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931}
2932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002933static int out_add_audio_effect(const struct audio_stream *stream __unused,
2934 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935{
2936 return 0;
2937}
2938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002939static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2940 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941{
2942 return 0;
2943}
2944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002945static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2946 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
2948 return -EINVAL;
2949}
2950
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002951static int out_get_presentation_position(const struct audio_stream_out *stream,
2952 uint64_t *frames, struct timespec *timestamp)
2953{
2954 struct stream_out *out = (struct stream_out *)stream;
2955 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002956 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002957
Ashish Jain5106d362016-05-11 19:23:33 +05302958 /* below piece of code is not guarded against any lock because audioFliner serializes
2959 * this operation and adev_close_output_stream( where out gets reset).
2960 */
2961 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2962 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2963 *frames = get_actual_pcm_frames_rendered(out);
2964 /* this is the best we can do */
2965 clock_gettime(CLOCK_MONOTONIC, timestamp);
2966 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2967 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2968 return 0;
2969 }
2970
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002971 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002972
Ashish Jain5106d362016-05-11 19:23:33 +05302973 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2974 ret = compress_get_tstamp(out->compr, &dsp_frames,
2975 &out->sample_rate);
2976 ALOGVV("%s rendered frames %ld sample_rate %d",
2977 __func__, dsp_frames, out->sample_rate);
2978 *frames = dsp_frames;
2979 if (ret < 0)
2980 ret = -errno;
2981 if (-ENETRESET == ret) {
2982 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2983 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2984 ret = -EINVAL;
2985 } else
2986 ret = 0;
2987 /* this is the best we can do */
2988 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002989 } else {
2990 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002991 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002992 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2993 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002994 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002995 // This adjustment accounts for buffering after app processor.
2996 // It is based on estimated DSP latency per use case, rather than exact.
2997 signed_frames -=
2998 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2999
Eric Laurent949a0892013-09-20 09:20:13 -07003000 // It would be unusual for this value to be negative, but check just in case ...
3001 if (signed_frames >= 0) {
3002 *frames = signed_frames;
3003 ret = 0;
3004 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003005 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303006 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3007 *frames = out->written;
3008 clock_gettime(CLOCK_MONOTONIC, timestamp);
3009 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003010 }
3011 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003012 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003013 return ret;
3014}
3015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003016static int out_set_callback(struct audio_stream_out *stream,
3017 stream_callback_t callback, void *cookie)
3018{
3019 struct stream_out *out = (struct stream_out *)stream;
3020
3021 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003022 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023 out->offload_callback = callback;
3024 out->offload_cookie = cookie;
3025 pthread_mutex_unlock(&out->lock);
3026 return 0;
3027}
3028
3029static int out_pause(struct audio_stream_out* stream)
3030{
3031 struct stream_out *out = (struct stream_out *)stream;
3032 int status = -ENOSYS;
3033 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003034 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003035 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003036 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303038 struct audio_device *adev = out->dev;
3039 int snd_scard_state = get_snd_card_state(adev);
3040
3041 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3042 status = compress_pause(out->compr);
3043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003045
Mingming Yin21854652016-04-13 11:54:02 -07003046 if (audio_extn_passthru_is_active()) {
3047 ALOGV("offload use case, pause passthru");
3048 audio_extn_passthru_on_pause(out);
3049 }
3050
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303051 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003052 audio_extn_dts_notify_playback_state(out->usecase, 0,
3053 out->sample_rate, popcount(out->channel_mask),
3054 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 }
3056 pthread_mutex_unlock(&out->lock);
3057 }
3058 return status;
3059}
3060
3061static int out_resume(struct audio_stream_out* stream)
3062{
3063 struct stream_out *out = (struct stream_out *)stream;
3064 int status = -ENOSYS;
3065 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003066 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003067 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003069 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303071 struct audio_device *adev = out->dev;
3072 int snd_scard_state = get_snd_card_state(adev);
3073
Mingming Yin21854652016-04-13 11:54:02 -07003074 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3075 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3076 pthread_mutex_lock(&out->dev->lock);
3077 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003078 pthread_mutex_unlock(&out->dev->lock);
3079 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303080 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003081 }
3082 if (!status) {
3083 out->offload_state = OFFLOAD_STATE_PLAYING;
3084 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303085 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3087 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 }
3089 pthread_mutex_unlock(&out->lock);
3090 }
3091 return status;
3092}
3093
3094static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3095{
3096 struct stream_out *out = (struct stream_out *)stream;
3097 int status = -ENOSYS;
3098 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003099 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003100 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003101 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3102 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3103 else
3104 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3105 pthread_mutex_unlock(&out->lock);
3106 }
3107 return status;
3108}
3109
3110static int out_flush(struct audio_stream_out* stream)
3111{
3112 struct stream_out *out = (struct stream_out *)stream;
3113 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003114 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003115 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003116 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303118 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003120 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 return 0;
3122 }
3123 return -ENOSYS;
3124}
3125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126/** audio_stream_in implementation **/
3127static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3128{
3129 struct stream_in *in = (struct stream_in *)stream;
3130
3131 return in->config.rate;
3132}
3133
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003134static int in_set_sample_rate(struct audio_stream *stream __unused,
3135 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136{
3137 return -ENOSYS;
3138}
3139
3140static size_t in_get_buffer_size(const struct audio_stream *stream)
3141{
3142 struct stream_in *in = (struct stream_in *)stream;
3143
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003144 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3145 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003146 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3147 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003148
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003149 return in->config.period_size * in->af_period_multiplier *
3150 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151}
3152
3153static uint32_t in_get_channels(const struct audio_stream *stream)
3154{
3155 struct stream_in *in = (struct stream_in *)stream;
3156
3157 return in->channel_mask;
3158}
3159
3160static audio_format_t in_get_format(const struct audio_stream *stream)
3161{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003162 struct stream_in *in = (struct stream_in *)stream;
3163
3164 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165}
3166
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003167static int in_set_format(struct audio_stream *stream __unused,
3168 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169{
3170 return -ENOSYS;
3171}
3172
3173static int in_standby(struct audio_stream *stream)
3174{
3175 struct stream_in *in = (struct stream_in *)stream;
3176 struct audio_device *adev = in->dev;
3177 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303178 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3179 stream, in->usecase, use_case_table[in->usecase]);
3180
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003181 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003182 if (!in->standby && in->is_st_session) {
3183 ALOGD("%s: sound trigger pcm stop lab", __func__);
3184 audio_extn_sound_trigger_stop_lab(in);
3185 in->standby = 1;
3186 }
3187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003189 if (adev->adm_deregister_stream)
3190 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3191
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003192 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003194 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3195 voice_extn_compress_voip_close_input_stream(stream);
3196 ALOGD("VOIP input entered standby");
3197 } else {
3198 if (in->pcm) {
3199 pcm_close(in->pcm);
3200 in->pcm = NULL;
3201 }
3202 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003203 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003204 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 }
3206 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003207 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 return status;
3209}
3210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003211static int in_dump(const struct audio_stream *stream __unused,
3212 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213{
3214 return 0;
3215}
3216
3217static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3218{
3219 struct stream_in *in = (struct stream_in *)stream;
3220 struct audio_device *adev = in->dev;
3221 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003223 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303225 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 parms = str_parms_create_str(kvpairs);
3227
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303228 if (!parms)
3229 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003230 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003231 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003232
3233 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3234 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 val = atoi(value);
3236 /* no audio source uses val == 0 */
3237 if ((in->source != val) && (val != 0)) {
3238 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003239 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3240 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3241 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003242 (in->config.rate == 8000 || in->config.rate == 16000 ||
3243 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003244 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003245 err = voice_extn_compress_voip_open_input_stream(in);
3246 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003247 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003248 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003249 }
3250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 }
3252 }
3253
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003254 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3255 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003257 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 in->device = val;
3259 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003260 if (!in->standby && !in->is_st_session) {
3261 ALOGV("update input routing change");
3262 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003263 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265 }
3266 }
3267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003269 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270
3271 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303272error:
Eric Laurent994a6932013-07-17 11:51:42 -07003273 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 return ret;
3275}
3276
3277static char* in_get_parameters(const struct audio_stream *stream,
3278 const char *keys)
3279{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003280 struct stream_in *in = (struct stream_in *)stream;
3281 struct str_parms *query = str_parms_create_str(keys);
3282 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003283 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003284
3285 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003286 if (reply) {
3287 str_parms_destroy(reply);
3288 }
3289 if (query) {
3290 str_parms_destroy(query);
3291 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003292 ALOGE("in_get_parameters: failed to create query or reply");
3293 return NULL;
3294 }
3295
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003296 ALOGV("%s: enter: keys - %s", __func__, keys);
3297
3298 voice_extn_in_get_parameters(in, query, reply);
3299
3300 str = str_parms_to_str(reply);
3301 str_parms_destroy(query);
3302 str_parms_destroy(reply);
3303
3304 ALOGV("%s: exit: returns - %s", __func__, str);
3305 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int in_set_gain(struct audio_stream_in *stream __unused,
3309 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return 0;
3312}
3313
3314static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3315 size_t bytes)
3316{
3317 struct stream_in *in = (struct stream_in *)stream;
3318 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303319 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303320 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303321 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003323 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303324
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003325 if (in->is_st_session) {
3326 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3327 /* Read from sound trigger HAL */
3328 audio_extn_sound_trigger_read(in, buffer, bytes);
3329 pthread_mutex_unlock(&in->lock);
3330 return bytes;
3331 }
3332
Ashish Jainbbce4322016-02-16 13:25:27 +05303333 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003334 ALOGD(" %s: sound card is not active/SSR state", __func__);
3335 ret= -EIO;;
3336 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303337 }
3338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003340 pthread_mutex_lock(&adev->lock);
3341 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3342 ret = voice_extn_compress_voip_start_input_stream(in);
3343 else
3344 ret = start_input_stream(in);
3345 pthread_mutex_unlock(&adev->lock);
3346 if (ret != 0) {
3347 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 }
3349 in->standby = 0;
3350 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003352 // what's the duration requested by the client?
3353 long ns = 0;
3354
3355 if (in->config.rate)
3356 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3357 in->config.rate;
3358
3359 request_in_focus(in, ns);
3360 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303363 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003364 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303365 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003366 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003367 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003368 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303369 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003370 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303371 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3372 if (bytes % 4 == 0) {
3373 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3374 int_buf_stream = buffer;
3375 for (size_t itt=0; itt < bytes/4 ; itt++) {
3376 int_buf_stream[itt] >>= 8;
3377 }
3378 } else {
3379 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3380 ret = -EINVAL;
3381 goto exit;
3382 }
3383 } if (ret < 0) {
3384 ret = -errno;
3385 }
3386 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 }
3388
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003389 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 /*
3392 * Instead of writing zeroes here, we could trust the hardware
3393 * to always provide zeroes when muted.
3394 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303395 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3396 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 memset(buffer, 0, bytes);
3398
3399exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303400 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303401 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003402 if (-ENETRESET == ret)
3403 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 pthread_mutex_unlock(&in->lock);
3406
3407 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303408 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303409 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303410 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303411 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303412 in->standby = true;
3413 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303414 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003416 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303417 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303418 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 }
3420 return bytes;
3421}
3422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003423static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424{
3425 return 0;
3426}
3427
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003428static int add_remove_audio_effect(const struct audio_stream *stream,
3429 effect_handle_t effect,
3430 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003432 struct stream_in *in = (struct stream_in *)stream;
3433 int status = 0;
3434 effect_descriptor_t desc;
3435
3436 status = (*effect)->get_descriptor(effect, &desc);
3437 if (status != 0)
3438 return status;
3439
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003440 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003441 pthread_mutex_lock(&in->dev->lock);
3442 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3443 in->enable_aec != enable &&
3444 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3445 in->enable_aec = enable;
3446 if (!in->standby)
3447 select_devices(in->dev, in->usecase);
3448 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003449 if (in->enable_ns != enable &&
3450 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3451 in->enable_ns = enable;
3452 if (!in->standby)
3453 select_devices(in->dev, in->usecase);
3454 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003455 pthread_mutex_unlock(&in->dev->lock);
3456 pthread_mutex_unlock(&in->lock);
3457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 return 0;
3459}
3460
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003461static int in_add_audio_effect(const struct audio_stream *stream,
3462 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463{
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003465 return add_remove_audio_effect(stream, effect, true);
3466}
3467
3468static int in_remove_audio_effect(const struct audio_stream *stream,
3469 effect_handle_t effect)
3470{
Eric Laurent994a6932013-07-17 11:51:42 -07003471 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003472 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473}
3474
3475static int adev_open_output_stream(struct audio_hw_device *dev,
3476 audio_io_handle_t handle,
3477 audio_devices_t devices,
3478 audio_output_flags_t flags,
3479 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003480 struct audio_stream_out **stream_out,
3481 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482{
3483 struct audio_device *adev = (struct audio_device *)dev;
3484 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303485 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003486 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303489
3490 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3491 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003492 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303493 return -EINVAL;
3494 }
3495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3497
Mingming Yin3a941d42016-02-17 18:08:05 -08003498 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3499 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303500 devices, flags, &out->stream);
3501
3502
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003503 if (!out) {
3504 return -ENOMEM;
3505 }
3506
Haynes Mathew George204045b2015-02-25 20:32:03 -08003507 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003508 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003509 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 if (devices == AUDIO_DEVICE_NONE)
3512 devices = AUDIO_DEVICE_OUT_SPEAKER;
3513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 out->flags = flags;
3515 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003516 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003517 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 out->sample_rate = config->sample_rate;
3519 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3520 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003521 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003522 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003523 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303524 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Mingming Yin3a941d42016-02-17 18:08:05 -08003526 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3527 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3528 pthread_mutex_lock(&adev->lock);
3529 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3530 ret = read_hdmi_sink_caps(out);
3531 pthread_mutex_unlock(&adev->lock);
3532 if (ret != 0) {
3533 if (ret == -ENOSYS) {
3534 /* ignore and go with default */
3535 ret = 0;
3536 } else {
3537 ALOGE("error reading hdmi sink caps");
3538 goto error_open;
3539 }
3540 }
3541 }
3542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003544 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303545 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3546 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003547 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3548 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3549
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003550 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003551 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3552 /*
3553 * Do not handle stereo output in Multi-channel cases
3554 * Stereo case is handled in normal playback path
3555 */
3556 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3557 ret = AUDIO_CHANNEL_OUT_STEREO;
3558 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003559
3560 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3561 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003562 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003563 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003564 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003565
3566 if (config->sample_rate == 0)
3567 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3568 if (config->channel_mask == 0)
3569 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003570 if (config->format == 0)
3571 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003572
3573 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003575 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3577 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003579 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003581 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3582 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003583 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003584 ret = voice_extn_compress_voip_open_output_stream(out);
3585 if (ret != 0) {
3586 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3587 __func__, ret);
3588 goto error_open;
3589 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003590 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3591 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3592
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3594 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3595 ALOGE("%s: Unsupported Offload information", __func__);
3596 ret = -EINVAL;
3597 goto error_open;
3598 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003599
Mingming Yin3a941d42016-02-17 18:08:05 -08003600 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003601 if(config->offload_info.format == 0)
3602 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003603 if (config->offload_info.sample_rate == 0)
3604 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003605 }
3606
Mingming Yin90310102013-11-13 16:57:00 -08003607 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303608 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003609 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 ret = -EINVAL;
3611 goto error_open;
3612 }
3613
3614 out->compr_config.codec = (struct snd_codec *)
3615 calloc(1, sizeof(struct snd_codec));
3616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003617 if (!out->compr_config.codec) {
3618 ret = -ENOMEM;
3619 goto error_open;
3620 }
3621
vivek mehta0ea887a2015-08-26 14:01:20 -07003622 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303623 out->stream.pause = out_pause;
3624 out->stream.flush = out_flush;
3625 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003626 out->usecase = get_offload_usecase(adev, true);
3627 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003628 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003629 out->stream.set_callback = out_set_callback;
3630 out->stream.pause = out_pause;
3631 out->stream.resume = out_resume;
3632 out->stream.drain = out_drain;
3633 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003634 out->usecase = get_offload_usecase(adev, false);
3635 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003636 }
vivek mehta446c3962015-09-14 10:57:35 -07003637
3638 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003639 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3640 config->format == 0 && config->sample_rate == 0 &&
3641 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003642 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003643 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3644 } else {
3645 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3646 ret = -EEXIST;
3647 goto error_open;
3648 }
vivek mehta446c3962015-09-14 10:57:35 -07003649 }
3650
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651 if (config->offload_info.channel_mask)
3652 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003653 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003655 config->offload_info.channel_mask = config->channel_mask;
3656 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003657 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658 out->sample_rate = config->offload_info.sample_rate;
3659
Mingming Yin3ee55c62014-08-04 14:23:35 -07003660 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303662 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3663 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3664 audio_extn_dolby_send_ddp_endp_params(adev);
3665 audio_extn_dolby_set_dmid(adev);
3666 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003667
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003669 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003670 out->compr_config.codec->bit_rate =
3671 config->offload_info.bit_rate;
3672 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303673 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303675 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003676 /*TODO: Do we need to change it for passthrough */
3677 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678
Manish Dewangana6fc5442015-08-24 20:30:31 +05303679 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3680 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3681 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3682 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303683
3684 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3685 AUDIO_FORMAT_PCM) {
3686
3687 /*Based on platform support, configure appropriate alsa format for corresponding
3688 *hal input format.
3689 */
3690 out->compr_config.codec->format = hal_format_to_alsa(
3691 config->offload_info.format);
3692
Ashish Jain83a6cc22016-06-28 14:34:17 +05303693 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303694 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303695 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303696
3697 /*for direct PCM playback populate bit_width based on selected alsa format as
3698 *hal input format and alsa format might differ based on platform support.
3699 */
3700 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303701 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303702
3703 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3704
3705 /* Check if alsa session is configured with the same format as HAL input format,
3706 * if not then derive correct fragment size needed to accomodate the
3707 * conversion of HAL input format to alsa format.
3708 */
3709 audio_extn_utils_update_direct_pcm_fragment_size(out);
3710
3711 /*if hal input and output fragment size is different this indicates HAL input format is
3712 *not same as the alsa format
3713 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303714 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303715 /*Allocate a buffer to convert input data to the alsa configured format.
3716 *size of convert buffer is equal to the size required to hold one fragment size
3717 *worth of pcm data, this is because flinger does not write more than fragment_size
3718 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303719 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3720 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303721 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3722 ret = -ENOMEM;
3723 goto error_open;
3724 }
3725 }
3726 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3727 out->compr_config.fragment_size =
3728 audio_extn_passthru_get_buffer_size(&config->offload_info);
3729 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3730 } else {
3731 out->compr_config.fragment_size =
3732 platform_get_compress_offload_buffer_size(&config->offload_info);
3733 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3734 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003735
Amit Shekhar6f461b12014-08-01 14:52:58 -07003736 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303737 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003738
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003739 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3740 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003741
Alexy Josephaa54c872014-12-03 02:46:47 -08003742
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003743 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303744 out->send_next_track_params = false;
3745 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003746 out->offload_state = OFFLOAD_STATE_IDLE;
3747 out->playback_started = 0;
3748
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003749 audio_extn_dts_create_state_notifier_node(out->usecase);
3750
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003751 create_offload_callback_thread(out);
3752 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3753 __func__, config->offload_info.version,
3754 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303755
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303756 /*Check if DSD audio format is supported in codec
3757 *and there is no active native DSD use case
3758 */
3759
3760 if ((config->format == AUDIO_FORMAT_DSD) &&
3761 (!platform_check_codec_dsd_support(adev->platform) ||
3762 audio_is_dsd_native_stream_active(adev))) {
3763 ret = -EINVAL;
3764 goto error_open;
3765 }
3766
Ashish Jain5106d362016-05-11 19:23:33 +05303767 /* Disable gapless if any of the following is true
3768 * passthrough playback
3769 * AV playback
3770 * Direct PCM playback
3771 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303772 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303773 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303774 config->offload_info.has_video ||
3775 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3776 check_and_set_gapless_mode(adev, false);
3777 } else
3778 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003779
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303780 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003781 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3782 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303783 if (config->format == AUDIO_FORMAT_DSD) {
3784 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3785 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3786 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003787 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303788 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003789 if (ret != 0) {
3790 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3791 __func__, ret);
3792 goto error_open;
3793 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003794 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3795 if (config->sample_rate == 0)
3796 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3797 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3798 config->sample_rate != 8000) {
3799 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3800 ret = -EINVAL;
3801 goto error_open;
3802 }
3803 out->sample_rate = config->sample_rate;
3804 out->config.rate = config->sample_rate;
3805 if (config->format == AUDIO_FORMAT_DEFAULT)
3806 config->format = AUDIO_FORMAT_PCM_16_BIT;
3807 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3808 config->format = AUDIO_FORMAT_PCM_16_BIT;
3809 ret = -EINVAL;
3810 goto error_open;
3811 }
3812 out->format = config->format;
3813 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3814 out->config = pcm_config_afe_proxy_playback;
3815 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003816 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303817 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3818 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003819 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3820 out->flags);
3821 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303822 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3823 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3824 out->config = pcm_config_low_latency;
3825 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3826 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3827 out->config = pcm_config_deep_buffer;
3828 } else {
3829 /* primary path is the default path selected if no other outputs are available/suitable */
3830 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3831 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3832 }
3833 out->hal_ip_format = format = out->format;
3834 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3835 out->hal_op_format = pcm_format_to_hal(out->config.format);
3836 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3837 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003838 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303839 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3840 if (out->hal_ip_format != out->hal_op_format) {
3841 uint32_t buffer_size = out->config.period_size *
3842 format_to_bitwidth_table[out->hal_op_format] *
3843 out->config.channels;
3844 out->convert_buffer = calloc(1, buffer_size);
3845 if (out->convert_buffer == NULL){
3846 ALOGE("Allocation failed for convert buffer for size %d",
3847 out->compr_config.fragment_size);
3848 ret = -ENOMEM;
3849 goto error_open;
3850 }
3851 ALOGD("Convert buffer allocated of size %d", buffer_size);
3852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 }
3854
Ashish Jain83a6cc22016-06-28 14:34:17 +05303855 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3856 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3857
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003858 /* TODO remove this hardcoding and check why width is zero*/
3859 if (out->bit_width == 0)
3860 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003861 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3862 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003863 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303864 out->bit_width, out->channel_mask,
3865 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003866 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3867 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3868 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003869 if(adev->primary_output == NULL)
3870 adev->primary_output = out;
3871 else {
3872 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003873 ret = -EEXIST;
3874 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003875 }
3876 }
3877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 /* Check if this usecase is already existing */
3879 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003880 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3881 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003884 ret = -EEXIST;
3885 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 }
3887 pthread_mutex_unlock(&adev->lock);
3888
3889 out->stream.common.get_sample_rate = out_get_sample_rate;
3890 out->stream.common.set_sample_rate = out_set_sample_rate;
3891 out->stream.common.get_buffer_size = out_get_buffer_size;
3892 out->stream.common.get_channels = out_get_channels;
3893 out->stream.common.get_format = out_get_format;
3894 out->stream.common.set_format = out_set_format;
3895 out->stream.common.standby = out_standby;
3896 out->stream.common.dump = out_dump;
3897 out->stream.common.set_parameters = out_set_parameters;
3898 out->stream.common.get_parameters = out_get_parameters;
3899 out->stream.common.add_audio_effect = out_add_audio_effect;
3900 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3901 out->stream.get_latency = out_get_latency;
3902 out->stream.set_volume = out_set_volume;
3903 out->stream.write = out_write;
3904 out->stream.get_render_position = out_get_render_position;
3905 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003906 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003908 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003910 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003911 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912
3913 config->format = out->stream.common.get_format(&out->stream.common);
3914 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3915 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3916
3917 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303918 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003919 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003920
3921 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3922 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3923 popcount(out->channel_mask), out->playback_started);
3924
Eric Laurent994a6932013-07-17 11:51:42 -07003925 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003927
3928error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303929 if (out->convert_buffer)
3930 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003931 free(out);
3932 *stream_out = NULL;
3933 ALOGD("%s: exit: ret %d", __func__, ret);
3934 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935}
3936
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003937static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 struct audio_stream_out *stream)
3939{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 struct stream_out *out = (struct stream_out *)stream;
3941 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003942 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003943
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303944 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3945
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003946 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303947 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003948 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303949 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003950 if(ret != 0)
3951 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3952 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003953 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003954 out_standby(&stream->common);
3955
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003956 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003957 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003959 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 if (out->compr_config.codec != NULL)
3961 free(out->compr_config.codec);
3962 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003963
Ashish Jain83a6cc22016-06-28 14:34:17 +05303964 if (out->convert_buffer != NULL) {
3965 free(out->convert_buffer);
3966 out->convert_buffer = NULL;
3967 }
3968
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003969 if (adev->voice_tx_output == out)
3970 adev->voice_tx_output = NULL;
3971
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003972 pthread_cond_destroy(&out->cond);
3973 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003975 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976}
3977
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003978static void close_compress_sessions(struct audio_device *adev)
3979{
Mingming Yin7b762e72015-03-04 13:47:32 -08003980 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303981 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003982 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003983 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303984
3985 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003986 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303987 if (is_offload_usecase(usecase->id)) {
3988 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003989 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3990 out = usecase->stream.out;
3991 pthread_mutex_unlock(&adev->lock);
3992 out_standby(&out->stream.common);
3993 pthread_mutex_lock(&adev->lock);
3994 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303995 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003996 }
3997 pthread_mutex_unlock(&adev->lock);
3998}
3999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4001{
4002 struct audio_device *adev = (struct audio_device *)dev;
4003 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004005 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004006 int ret;
4007 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004009 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304012 if (!parms)
4013 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004014 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4015 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304016 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304017 if (strstr(snd_card_status, "OFFLINE")) {
4018 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304019 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004020 //close compress sessions on OFFLINE status
4021 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304022 } else if (strstr(snd_card_status, "ONLINE")) {
4023 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304024 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004025 //send dts hpx license if enabled
4026 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304027 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304028 }
4029
4030 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004031 status = voice_set_parameters(adev, parms);
4032 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004033 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004035 status = platform_set_parameters(adev->platform, parms);
4036 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004037 goto done;
4038
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004039 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4040 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004041 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4043 adev->bluetooth_nrec = true;
4044 else
4045 adev->bluetooth_nrec = false;
4046 }
4047
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004048 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4049 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4051 adev->screen_off = false;
4052 else
4053 adev->screen_off = true;
4054 }
4055
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004056 ret = str_parms_get_int(parms, "rotation", &val);
4057 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004058 bool reverse_speakers = false;
4059 switch(val) {
4060 // FIXME: note that the code below assumes that the speakers are in the correct placement
4061 // relative to the user when the device is rotated 90deg from its default rotation. This
4062 // assumption is device-specific, not platform-specific like this code.
4063 case 270:
4064 reverse_speakers = true;
4065 break;
4066 case 0:
4067 case 90:
4068 case 180:
4069 break;
4070 default:
4071 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004072 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004073 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004074 if (status == 0) {
4075 if (adev->speaker_lr_swap != reverse_speakers) {
4076 adev->speaker_lr_swap = reverse_speakers;
4077 // only update the selected device if there is active pcm playback
4078 struct audio_usecase *usecase;
4079 struct listnode *node;
4080 list_for_each(node, &adev->usecase_list) {
4081 usecase = node_to_item(node, struct audio_usecase, list);
4082 if (usecase->type == PCM_PLAYBACK) {
4083 select_devices(adev, usecase->id);
4084 break;
4085 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004086 }
4087 }
4088 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004089 }
4090
Mingming Yin514a8bc2014-07-29 15:22:21 -07004091 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4092 if (ret >= 0) {
4093 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4094 adev->bt_wb_speech_enabled = true;
4095 else
4096 adev->bt_wb_speech_enabled = false;
4097 }
4098
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004099 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4100 if (ret >= 0) {
4101 val = atoi(value);
4102 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4103 ALOGV("cache new edid");
4104 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004105 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4106 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004107 /*
4108 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4109 * Per AudioPolicyManager, USB device is higher priority than WFD.
4110 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4111 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4112 * starting voice call on USB
4113 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004114 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4115 if (ret >= 0) {
4116 audio_extn_usb_add_device(val, atoi(value));
4117 }
vivek mehta344576a2016-04-12 18:56:03 -07004118 ALOGV("detected USB connect .. disable proxy");
4119 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004120 }
4121 }
4122
4123 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4124 if (ret >= 0) {
4125 val = atoi(value);
4126 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4127 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004128 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004129 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4130 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4131 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4132 if (ret >= 0) {
4133 audio_extn_usb_remove_device(val, atoi(value));
4134 }
vivek mehta344576a2016-04-12 18:56:03 -07004135 ALOGV("detected USB disconnect .. enable proxy");
4136 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004137 }
4138 }
4139
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004140 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304141 // reconfigure should be done only after updating a2dpstate in audio extn
4142 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4143 if (ret >= 0) {
4144 struct audio_usecase *usecase;
4145 struct listnode *node;
4146 list_for_each(node, &adev->usecase_list) {
4147 usecase = node_to_item(node, struct audio_usecase, list);
4148 if ((usecase->type == PCM_PLAYBACK) &&
4149 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4150 ALOGD("reconfigure a2dp... forcing device switch");
4151 //force device switch to re configure encoder
4152 select_devices(adev, usecase->id);
4153 break;
4154 }
4155 }
4156 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004157
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004158done:
4159 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004160 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304161error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004162 ALOGV("%s: exit with code(%d)", __func__, status);
4163 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164}
4165
4166static char* adev_get_parameters(const struct audio_hw_device *dev,
4167 const char *keys)
4168{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004169 struct audio_device *adev = (struct audio_device *)dev;
4170 struct str_parms *reply = str_parms_create();
4171 struct str_parms *query = str_parms_create_str(keys);
4172 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304173 char value[256] = {0};
4174 int ret = 0;
4175
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004176 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004177 if (reply) {
4178 str_parms_destroy(reply);
4179 }
4180 if (query) {
4181 str_parms_destroy(query);
4182 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004183 ALOGE("adev_get_parameters: failed to create query or reply");
4184 return NULL;
4185 }
4186
Naresh Tannirud7205b62014-06-20 02:54:48 +05304187 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4188 sizeof(value));
4189 if (ret >=0) {
4190 int val = 1;
4191 pthread_mutex_lock(&adev->snd_card_status.lock);
4192 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4193 val = 0;
4194 pthread_mutex_unlock(&adev->snd_card_status.lock);
4195 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4196 goto exit;
4197 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004198
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004199 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004200 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004201 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004202 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304203 pthread_mutex_unlock(&adev->lock);
4204
Naresh Tannirud7205b62014-06-20 02:54:48 +05304205exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004206 str = str_parms_to_str(reply);
4207 str_parms_destroy(query);
4208 str_parms_destroy(reply);
4209
4210 ALOGV("%s: exit: returns - %s", __func__, str);
4211 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212}
4213
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004214static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215{
4216 return 0;
4217}
4218
4219static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4220{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004221 int ret;
4222 struct audio_device *adev = (struct audio_device *)dev;
4223 pthread_mutex_lock(&adev->lock);
4224 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004225 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004226 pthread_mutex_unlock(&adev->lock);
4227 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228}
4229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004230static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4231 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232{
4233 return -ENOSYS;
4234}
4235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004236static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4237 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238{
4239 return -ENOSYS;
4240}
4241
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004242static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4243 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244{
4245 return -ENOSYS;
4246}
4247
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004248static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4249 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250{
4251 return -ENOSYS;
4252}
4253
4254static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4255{
4256 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 pthread_mutex_lock(&adev->lock);
4259 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004260 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004262 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004263 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004264 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004265 adev->current_call_output = NULL;
4266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 }
4268 pthread_mutex_unlock(&adev->lock);
4269 return 0;
4270}
4271
4272static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4273{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004274 int ret;
4275
4276 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004277 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004278 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4279 pthread_mutex_unlock(&adev->lock);
4280
4281 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282}
4283
4284static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4285{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004286 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 return 0;
4288}
4289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004290static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 const struct audio_config *config)
4292{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004293 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004295 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4296 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004297}
4298
4299static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004300 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301 audio_devices_t devices,
4302 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004303 struct audio_stream_in **stream_in,
4304 audio_input_flags_t flags __unused,
4305 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004306 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307{
4308 struct audio_device *adev = (struct audio_device *)dev;
4309 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004310 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004311 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004312 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304315 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4316 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319
4320 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004321
4322 if (!in) {
4323 ALOGE("failed to allocate input stream");
4324 return -ENOMEM;
4325 }
4326
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304327 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304328 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4329 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004330 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004331 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 in->stream.common.get_sample_rate = in_get_sample_rate;
4334 in->stream.common.set_sample_rate = in_set_sample_rate;
4335 in->stream.common.get_buffer_size = in_get_buffer_size;
4336 in->stream.common.get_channels = in_get_channels;
4337 in->stream.common.get_format = in_get_format;
4338 in->stream.common.set_format = in_set_format;
4339 in->stream.common.standby = in_standby;
4340 in->stream.common.dump = in_dump;
4341 in->stream.common.set_parameters = in_set_parameters;
4342 in->stream.common.get_parameters = in_get_parameters;
4343 in->stream.common.add_audio_effect = in_add_audio_effect;
4344 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4345 in->stream.set_gain = in_set_gain;
4346 in->stream.read = in_read;
4347 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4348
4349 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004350 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 in->standby = 1;
4353 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004354 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004355 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356
4357 /* Update config params with the requested sample rate and channels */
4358 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004359 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4360 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4361 is_low_latency = true;
4362#if LOW_LATENCY_CAPTURE_USE_CASE
4363 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4364#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004365 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004366 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004367
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004368 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004369 if (in->realtime) {
4370 in->config = pcm_config_audio_capture_rt;
4371 in->sample_rate = in->config.rate;
4372 in->af_period_multiplier = af_period_multiplier;
4373 } else {
4374 in->config = pcm_config_audio_capture;
4375 in->config.rate = config->sample_rate;
4376 in->sample_rate = config->sample_rate;
4377 in->af_period_multiplier = 1;
4378 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304379 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004381 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304382 if (adev->mode != AUDIO_MODE_IN_CALL) {
4383 ret = -EINVAL;
4384 goto err_open;
4385 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004386 if (config->sample_rate == 0)
4387 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4388 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4389 config->sample_rate != 8000) {
4390 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4391 ret = -EINVAL;
4392 goto err_open;
4393 }
4394 if (config->format == AUDIO_FORMAT_DEFAULT)
4395 config->format = AUDIO_FORMAT_PCM_16_BIT;
4396 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4397 config->format = AUDIO_FORMAT_PCM_16_BIT;
4398 ret = -EINVAL;
4399 goto err_open;
4400 }
4401
4402 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4403 in->config = pcm_config_afe_proxy_record;
4404 in->config.channels = channel_count;
4405 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304406 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304407 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4408 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004409 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004410 audio_extn_compr_cap_format_supported(config->format) &&
4411 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004412 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004413 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304414 /* restrict 24 bit capture for unprocessed source only
4415 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4416 */
4417 if (config->format == AUDIO_FORMAT_DEFAULT) {
4418 config->format = AUDIO_FORMAT_PCM_16_BIT;
4419 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4420 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4421 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4422 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4423 bool ret_error = false;
4424 in->bit_width = 24;
4425 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4426 from HAL is 24_packed and 8_24
4427 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4428 24_packed return error indicating supported format is 24_packed
4429 *> In case of any other source requesting 24 bit or float return error
4430 indicating format supported is 16 bit only.
4431
4432 on error flinger will retry with supported format passed
4433 */
4434 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4435 (source != AUDIO_SOURCE_CAMCORDER)) {
4436 config->format = AUDIO_FORMAT_PCM_16_BIT;
4437 if( config->sample_rate > 48000)
4438 config->sample_rate = 48000;
4439 ret_error = true;
4440 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4441 in->config.format = PCM_FORMAT_S24_3LE;
4442 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4443 in->config.format = PCM_FORMAT_S24_LE;
4444 } else {
4445 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4446 ret_error = true;
4447 }
4448
4449 if (ret_error) {
4450 ret = -EINVAL;
4451 goto err_open;
4452 }
4453 }
4454
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004455 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004456 if (!in->realtime) {
4457 in->format = config->format;
4458 frame_size = audio_stream_in_frame_size(&in->stream);
4459 buffer_size = get_input_buffer_size(config->sample_rate,
4460 config->format,
4461 channel_count,
4462 is_low_latency);
4463 in->config.period_size = buffer_size / frame_size;
4464 }
4465
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004466 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4467 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4468 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004469 (in->config.rate == 8000 || in->config.rate == 16000 ||
4470 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004471 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4472 voice_extn_compress_voip_open_input_stream(in);
4473 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004476 /* This stream could be for sound trigger lab,
4477 get sound trigger pcm if present */
4478 audio_extn_sound_trigger_check_and_get_session(in);
4479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004481 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004482 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483
4484err_open:
4485 free(in);
4486 *stream_in = NULL;
4487 return ret;
4488}
4489
4490static void adev_close_input_stream(struct audio_hw_device *dev,
4491 struct audio_stream_in *stream)
4492{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004493 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004494 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004495 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304496
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304497 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004498
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304499 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004500 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304501
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004502 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304503 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004504 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304505 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004506 if (ret != 0)
4507 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4508 __func__, ret);
4509 } else
4510 in_standby(&stream->common);
4511
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004512 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004513 audio_extn_ssr_deinit();
4514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515
Mingming Yine62d7842013-10-25 16:26:03 -07004516 if(audio_extn_compr_cap_enabled() &&
4517 audio_extn_compr_cap_format_supported(in->config.format))
4518 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004519
Mingming Yinfd7607b2016-01-22 12:48:44 -08004520 if (in->is_st_session) {
4521 ALOGV("%s: sound trigger pcm stop lab", __func__);
4522 audio_extn_sound_trigger_stop_lab(in);
4523 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004524 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525 return;
4526}
4527
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004528static int adev_dump(const audio_hw_device_t *device __unused,
4529 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530{
4531 return 0;
4532}
4533
4534static int adev_close(hw_device_t *device)
4535{
4536 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004537
4538 if (!adev)
4539 return 0;
4540
4541 pthread_mutex_lock(&adev_init_lock);
4542
4543 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004544 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004545 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004546 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004547 audio_route_free(adev->audio_route);
4548 free(adev->snd_dev_ref_cnt);
4549 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004550 if (adev->adm_deinit)
4551 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004552 free(device);
4553 adev = NULL;
4554 }
4555 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 return 0;
4558}
4559
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004560/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4561 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4562 * just that it _might_ work.
4563 */
4564static int period_size_is_plausible_for_low_latency(int period_size)
4565{
4566 switch (period_size) {
4567 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004568 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004569 case 240:
4570 case 320:
4571 case 480:
4572 return 1;
4573 default:
4574 return 0;
4575 }
4576}
4577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578static int adev_open(const hw_module_t *module, const char *name,
4579 hw_device_t **device)
4580{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004581 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4583
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004584 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004585 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004586 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004587 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004588 ALOGD("%s: returning existing instance of adev", __func__);
4589 ALOGD("%s: exit", __func__);
4590 pthread_mutex_unlock(&adev_init_lock);
4591 return 0;
4592 }
4593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594 adev = calloc(1, sizeof(struct audio_device));
4595
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004596 if (!adev) {
4597 pthread_mutex_unlock(&adev_init_lock);
4598 return -ENOMEM;
4599 }
4600
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004601 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4604 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4605 adev->device.common.module = (struct hw_module_t *)module;
4606 adev->device.common.close = adev_close;
4607
4608 adev->device.init_check = adev_init_check;
4609 adev->device.set_voice_volume = adev_set_voice_volume;
4610 adev->device.set_master_volume = adev_set_master_volume;
4611 adev->device.get_master_volume = adev_get_master_volume;
4612 adev->device.set_master_mute = adev_set_master_mute;
4613 adev->device.get_master_mute = adev_get_master_mute;
4614 adev->device.set_mode = adev_set_mode;
4615 adev->device.set_mic_mute = adev_set_mic_mute;
4616 adev->device.get_mic_mute = adev_get_mic_mute;
4617 adev->device.set_parameters = adev_set_parameters;
4618 adev->device.get_parameters = adev_get_parameters;
4619 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4620 adev->device.open_output_stream = adev_open_output_stream;
4621 adev->device.close_output_stream = adev_close_output_stream;
4622 adev->device.open_input_stream = adev_open_input_stream;
4623 adev->device.close_input_stream = adev_close_input_stream;
4624 adev->device.dump = adev_dump;
4625
4626 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004628 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004629 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004632 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004633 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004634 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004635 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004636 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004637 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004638 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004639 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304640 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304641 adev->perf_lock_opts[0] = 0x101;
4642 adev->perf_lock_opts[1] = 0x20E;
4643 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304644
4645 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4646 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004648 adev->platform = platform_init(adev);
4649 if (!adev->platform) {
4650 free(adev->snd_dev_ref_cnt);
4651 free(adev);
4652 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4653 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004654 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004655 return -EINVAL;
4656 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004657
Naresh Tanniru4c630392014-05-12 01:05:52 +05304658 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4659
Eric Laurentc4aef752013-09-12 17:45:53 -07004660 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4661 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4662 if (adev->visualizer_lib == NULL) {
4663 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4664 } else {
4665 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4666 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004667 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004668 "visualizer_hal_start_output");
4669 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004670 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004671 "visualizer_hal_stop_output");
4672 }
4673 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004674 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004675 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004676
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004677 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4678 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4679 if (adev->offload_effects_lib == NULL) {
4680 ALOGE("%s: DLOPEN failed for %s", __func__,
4681 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4682 } else {
4683 ALOGV("%s: DLOPEN successful for %s", __func__,
4684 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4685 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304686 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004687 "offload_effects_bundle_hal_start_output");
4688 adev->offload_effects_stop_output =
4689 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4690 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004691 adev->offload_effects_set_hpx_state =
4692 (int (*)(bool))dlsym(adev->offload_effects_lib,
4693 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304694 adev->offload_effects_get_parameters =
4695 (void (*)(struct str_parms *, struct str_parms *))
4696 dlsym(adev->offload_effects_lib,
4697 "offload_effects_bundle_get_parameters");
4698 adev->offload_effects_set_parameters =
4699 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4700 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004701 }
4702 }
4703
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004704 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4705 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4706 if (adev->adm_lib == NULL) {
4707 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4708 } else {
4709 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4710 adev->adm_init = (adm_init_t)
4711 dlsym(adev->adm_lib, "adm_init");
4712 adev->adm_deinit = (adm_deinit_t)
4713 dlsym(adev->adm_lib, "adm_deinit");
4714 adev->adm_register_input_stream = (adm_register_input_stream_t)
4715 dlsym(adev->adm_lib, "adm_register_input_stream");
4716 adev->adm_register_output_stream = (adm_register_output_stream_t)
4717 dlsym(adev->adm_lib, "adm_register_output_stream");
4718 adev->adm_deregister_stream = (adm_deregister_stream_t)
4719 dlsym(adev->adm_lib, "adm_deregister_stream");
4720 adev->adm_request_focus = (adm_request_focus_t)
4721 dlsym(adev->adm_lib, "adm_request_focus");
4722 adev->adm_abandon_focus = (adm_abandon_focus_t)
4723 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004724 adev->adm_set_config = (adm_set_config_t)
4725 dlsym(adev->adm_lib, "adm_set_config");
4726 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4727 dlsym(adev->adm_lib, "adm_request_focus_v2");
4728 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4729 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4730 adev->adm_on_routing_change = (adm_on_routing_change_t)
4731 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004732 }
4733 }
4734
Mingming Yin514a8bc2014-07-29 15:22:21 -07004735 adev->bt_wb_speech_enabled = false;
4736
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004737 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 *device = &adev->device.common;
4739
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004740 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4741 &adev->streams_output_cfg_list);
4742
Kiran Kandi910e1862013-10-29 13:29:42 -07004743 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004744
4745 char value[PROPERTY_VALUE_MAX];
4746 int trial;
4747 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4748 trial = atoi(value);
4749 if (period_size_is_plausible_for_low_latency(trial)) {
4750 pcm_config_low_latency.period_size = trial;
4751 pcm_config_low_latency.start_threshold = trial / 4;
4752 pcm_config_low_latency.avail_min = trial / 4;
4753 configured_low_latency_capture_period_size = trial;
4754 }
4755 }
4756 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4757 trial = atoi(value);
4758 if (period_size_is_plausible_for_low_latency(trial)) {
4759 configured_low_latency_capture_period_size = trial;
4760 }
4761 }
4762
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004763 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4764 af_period_multiplier = atoi(value);
4765 if (af_period_multiplier < 0)
4766 af_period_multiplier = 2;
4767 else if (af_period_multiplier > 4)
4768 af_period_multiplier = 4;
4769
4770 ALOGV("new period_multiplier = %d", af_period_multiplier);
4771 }
4772
vivek mehta446c3962015-09-14 10:57:35 -07004773 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004774 pthread_mutex_unlock(&adev_init_lock);
4775
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004776 if (adev->adm_init)
4777 adev->adm_data = adev->adm_init();
4778
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304779 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004780 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 return 0;
4782}
4783
4784static struct hw_module_methods_t hal_module_methods = {
4785 .open = adev_open,
4786};
4787
4788struct audio_module HAL_MODULE_INFO_SYM = {
4789 .common = {
4790 .tag = HARDWARE_MODULE_TAG,
4791 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4792 .hal_api_version = HARDWARE_HAL_API_VERSION,
4793 .id = AUDIO_HARDWARE_MODULE_ID,
4794 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004795 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796 .methods = &hal_module_methods,
4797 },
4798};