blob: d73f92c5ddc5eb65c1a39a4a8079ad920091f6cd [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",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625/*
626 * Enable ASRC mode if native or DSD stream is active.
627 */
628static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
629{
630 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635
636 list_for_each(node, &adev->usecase_list) {
637 uc = node_to_item(node, struct audio_usecase, list);
638 curr_out = (struct stream_out*) uc->stream.out;
639
640 if (curr_out && PCM_PLAYBACK == uc->type) {
641 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
642 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
643 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
644 __func__);
645 audio_route_apply_and_update_path(adev->audio_route,
646 "asrc-mode");
647 adev->asrc_mode_enabled = true;
648 break;
649 }
650 }
651 }
652 }
653}
654
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700655int pcm_ioctl(struct pcm *pcm, int request, ...)
656{
657 va_list ap;
658 void * arg;
659 int pcm_fd = *(int*)pcm;
660
661 va_start(ap, request);
662 arg = va_arg(ap, void *);
663 va_end(ap);
664
665 return ioctl(pcm_fd, request, arg);
666}
667
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700668int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700672 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800673
674 if (usecase == NULL)
675 return -EINVAL;
676
677 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
678
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800684#ifdef DS1_DOLBY_DAP_ENABLED
685 audio_extn_dolby_set_dmid(adev);
686 audio_extn_dolby_set_endpoint(adev);
687#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700688 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700689 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530690 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700691 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530692 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800693 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700694 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700695 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700696 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 ALOGV("%s: exit", __func__);
698 return 0;
699}
700
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700701int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530707 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 if (usecase->type == PCM_CAPTURE)
712 snd_device = usecase->in_snd_device;
713 else
714 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800715 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700716 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700717 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700719 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530720 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 ALOGV("%s: exit", __func__);
722 return 0;
723}
724
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700725int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530728 int i, num_devices = 0;
729 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700730 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
731
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800732 if (snd_device < SND_DEVICE_MIN ||
733 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800734 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800735 return -EINVAL;
736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737
738 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700739
740 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
741 ALOGE("%s: Invalid sound device returned", __func__);
742 return -EINVAL;
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700745 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700746 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 return 0;
748 }
749
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530750
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700751 if (audio_extn_spkr_prot_is_enabled())
752 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800754 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
755 audio_extn_spkr_prot_is_enabled()) {
756 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700757 adev->snd_dev_ref_cnt[snd_device]--;
758 return -EINVAL;
759 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200760 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800761 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800762 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200763 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 return -EINVAL;
765 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530766 } else if (platform_can_split_snd_device(adev->platform, snd_device,
767 &num_devices, new_snd_devices)) {
768 for (i = 0; i < num_devices; i++) {
769 enable_snd_device(adev, new_snd_devices[i]);
770 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530773
774 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
775 (audio_extn_a2dp_start_playback() < 0)) {
776 ALOGE(" fail to configure A2dp control path ");
777 return -EINVAL;
778 }
779
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
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800838 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
839 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700840 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530841 } else if (platform_can_split_snd_device(adev->platform, snd_device,
842 &num_devices, new_snd_devices)) {
843 for (i = 0; i < num_devices; i++) {
844 disable_snd_device(adev, new_snd_devices[i]);
845 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300846 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700847 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300848 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700849
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530850 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
851 audio_extn_a2dp_stop_playback();
852
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700853 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530855 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 adev->native_playback_enabled) {
857 ALOGD("%s: %d: napb: disabling native mode in hardware",
858 __func__, __LINE__);
859 audio_route_reset_and_update_path(adev->audio_route,
860 "true-native-mode");
861 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530862 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
863 adev->asrc_mode_enabled) {
864 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
865 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
866 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530868
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200869 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700870 audio_extn_sound_trigger_update_device_status(snd_device,
871 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530872 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800873 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 return 0;
877}
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530880 struct audio_usecase *uc_info,
881 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882{
883 struct listnode *node;
884 struct audio_usecase *usecase;
885 bool switch_device[AUDIO_USECASE_MAX];
886 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530887 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 /*
889 * This function is to make sure that all the usecases that are active on
890 * the hardware codec backend are always routed to any one device that is
891 * handled by the hardware codec.
892 * For example, if low-latency and deep-buffer usecases are currently active
893 * on speaker and out_set_parameters(headset) is received on low-latency
894 * output, then we have to make sure deep-buffer is also switched to headset,
895 * because of the limitation that both the devices cannot be enabled
896 * at the same time as they share the same backend.
897 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700898 /*
899 * This call is to check if we need to force routing for a particular stream
900 * If there is a backend configuration change for the device when a
901 * new stream starts, then ADM needs to be closed and re-opened with the new
902 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800903 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700904 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800905 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
906 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
912 audio_extn_a2dp_is_force_device_switch()) {
913 force_routing = true;
914 force_restart_session = true;
915 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 ALOGD("%s:becf: force routing %d", __func__, force_routing);
917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800919 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 for (i = 0; i < AUDIO_USECASE_MAX; i++)
922 switch_device[i] = false;
923
924 list_for_each(node, &adev->usecase_list) {
925 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800926
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530927 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
928 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530929 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530930 platform_get_snd_device_name(usecase->out_snd_device),
931 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800932 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530933 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530934 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530935 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
936 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530937 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530938 (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
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001089 /* Cache ext disp type */
1090 ret = platform_get_ext_disp_type(adev->platform);
1091 if (ret < 0) {
1092 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1093 return ret;
1094 }
1095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001098 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1101 case 6:
1102 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1103 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1104 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1105 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1107 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 break;
1109 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001110 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001111 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 break;
1113 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001114
1115 // check channel format caps
1116 i = 0;
1117 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1118 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1119 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1120 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1121 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1122 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1123 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1124 }
1125
1126 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1127 ALOGV(":%s HDMI supports DTS format", __func__);
1128 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1129 }
1130
1131 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1132 ALOGV(":%s HDMI supports DTS HD format", __func__);
1133 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1134 }
1135
1136
1137 // check sample rate caps
1138 i = 0;
1139 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1140 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1141 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1142 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1143 }
1144 }
1145
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147}
1148
Alexy Josephb1379942016-01-29 15:49:38 -08001149audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151{
1152 struct audio_usecase *usecase;
1153 struct listnode *node;
1154
1155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001157 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001158 ALOGV("%s: usecase id %d", __func__, usecase->id);
1159 return usecase->id;
1160 }
1161 }
1162 return USECASE_INVALID;
1163}
1164
Alexy Josephb1379942016-01-29 15:49:38 -08001165struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001166 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167{
1168 struct audio_usecase *usecase;
1169 struct listnode *node;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->id == uc_id)
1174 return usecase;
1175 }
1176 return NULL;
1177}
1178
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179/*
1180 * is a true native playback active
1181 */
1182bool audio_is_true_native_stream_active(struct audio_device *adev)
1183{
1184 bool active = false;
1185 int i = 0;
1186 struct listnode *node;
1187
1188 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1189 ALOGV("%s:napb: not in true mode or non hdphones device",
1190 __func__);
1191 active = false;
1192 goto exit;
1193 }
1194
1195 list_for_each(node, &adev->usecase_list) {
1196 struct audio_usecase *uc;
1197 uc = node_to_item(node, struct audio_usecase, list);
1198 struct stream_out *curr_out =
1199 (struct stream_out*) uc->stream.out;
1200
1201 if (curr_out && PCM_PLAYBACK == uc->type) {
1202 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1203 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1204 uc->id, curr_out->sample_rate,
1205 curr_out->bit_width,
1206 platform_get_snd_device_name(uc->out_snd_device));
1207
1208 if (is_offload_usecase(uc->id) &&
1209 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1210 active = true;
1211 ALOGD("%s:napb:native stream detected", __func__);
1212 }
1213 }
1214 }
1215exit:
1216 return active;
1217}
1218
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301219/*
1220 * if native DSD playback active
1221 */
1222bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1223{
1224 bool active = false;
1225 struct listnode *node = NULL;
1226 struct audio_usecase *uc = NULL;
1227 struct stream_out *curr_out = NULL;
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 uc = node_to_item(node, struct audio_usecase, list);
1231 curr_out = (struct stream_out*) uc->stream.out;
1232
1233 if (curr_out && PCM_PLAYBACK == uc->type &&
1234 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1235 active = true;
1236 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301237 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301238 }
1239 }
1240 return active;
1241}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301242
1243static bool force_device_switch(struct audio_usecase *usecase)
1244{
1245 bool ret = false;
1246 bool is_it_true_mode = false;
1247
1248 if (is_offload_usecase(usecase->id) &&
1249 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001250 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1251 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1252 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301253 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1254 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1255 (!is_it_true_mode && adev->native_playback_enabled)){
1256 ret = true;
1257 ALOGD("napb: time to toggle native mode");
1258 }
1259 }
1260
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301261 // Force all a2dp output devices to reconfigure for proper AFE encode format
1262 if((usecase->stream.out) &&
1263 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1264 audio_extn_a2dp_is_force_device_switch()) {
1265 ALOGD("Force a2dp device switch to update new encoder config");
1266 ret = true;
1267 }
1268
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301269 return ret;
1270}
1271
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001272int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001274 snd_device_t out_snd_device = SND_DEVICE_NONE;
1275 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276 struct audio_usecase *usecase = NULL;
1277 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001278 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001279 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001280 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301283 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1284
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001285 usecase = get_usecase_from_list(adev, uc_id);
1286 if (usecase == NULL) {
1287 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1288 return -EINVAL;
1289 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001291 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001292 (usecase->type == VOIP_CALL) ||
1293 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301294 if(usecase->stream.out == NULL) {
1295 ALOGE("%s: stream.out is NULL", __func__);
1296 return -EINVAL;
1297 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001298 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001299 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001300 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001301 usecase->devices = usecase->stream.out->devices;
1302 } else {
1303 /*
1304 * If the voice call is active, use the sound devices of voice call usecase
1305 * so that it would not result any device switch. All the usecases will
1306 * be switched to new device when select_devices() is called for voice call
1307 * usecase. This is to avoid switching devices for voice call when
1308 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001309 * choose voice call device only if the use case device is
1310 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001312 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001313 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001314 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001315 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1316 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301317 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1318 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001319 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320 in_snd_device = vc_usecase->in_snd_device;
1321 out_snd_device = vc_usecase->out_snd_device;
1322 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001323 } else if (voice_extn_compress_voip_is_active(adev)) {
1324 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001325 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001326 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1327 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001328 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001329 in_snd_device = voip_usecase->in_snd_device;
1330 out_snd_device = voip_usecase->out_snd_device;
1331 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001332 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001333 hfp_ucid = audio_extn_hfp_get_usecase();
1334 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001335 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001336 in_snd_device = hfp_usecase->in_snd_device;
1337 out_snd_device = hfp_usecase->out_snd_device;
1338 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 }
1340 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301341 if (usecase->stream.out == NULL) {
1342 ALOGE("%s: stream.out is NULL", __func__);
1343 return -EINVAL;
1344 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001345 usecase->devices = usecase->stream.out->devices;
1346 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001347 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001348 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001349 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001350 if (usecase->stream.out == adev->primary_output &&
1351 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001352 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001353 select_devices(adev, adev->active_input->usecase);
1354 }
1355 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001356 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301357 if (usecase->stream.in == NULL) {
1358 ALOGE("%s: stream.in is NULL", __func__);
1359 return -EINVAL;
1360 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001361 usecase->devices = usecase->stream.in->device;
1362 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001363 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001364 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001365 if (adev->active_input &&
1366 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301367 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1368 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1369 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001370 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001371 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001372 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1373 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001374 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001375 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001376 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377 }
1378 }
1379
1380 if (out_snd_device == usecase->out_snd_device &&
1381 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301382
1383 if (!force_device_switch(usecase))
1384 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 }
1386
sangwoobc677242013-08-08 16:53:43 +09001387 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001388 out_snd_device, platform_get_snd_device_name(out_snd_device),
1389 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391 /*
1392 * Limitation: While in call, to do a device switch we need to disable
1393 * and enable both RX and TX devices though one of them is same as current
1394 * device.
1395 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001396 if ((usecase->type == VOICE_CALL) &&
1397 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1398 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001399 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001400 }
1401
1402 if (((usecase->type == VOICE_CALL) ||
1403 (usecase->type == VOIP_CALL)) &&
1404 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1405 /* Disable sidetone only if voice/voip call already exists */
1406 if (voice_is_call_state_active(adev) ||
1407 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001408 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001409 }
1410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 /* Disable current sound devices */
1412 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 disable_audio_route(adev, usecase);
1414 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 }
1416
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001418 disable_audio_route(adev, usecase);
1419 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420 }
1421
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001422 /* Applicable only on the targets that has external modem.
1423 * New device information should be sent to modem before enabling
1424 * the devices to reduce in-call device switch time.
1425 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001426 if ((usecase->type == VOICE_CALL) &&
1427 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1428 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001429 status = platform_switch_voice_call_enable_device_config(adev->platform,
1430 out_snd_device,
1431 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001432 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001433
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 /* Enable new sound devices */
1435 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001436 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001437 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 }
1439
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001440 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301441 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001442 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444
Avinash Vaish71a8b972014-07-24 15:36:33 +05301445 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001446 status = platform_switch_voice_call_device_post(adev->platform,
1447 out_snd_device,
1448 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301449 enable_audio_route_for_voice_usecases(adev, usecase);
1450 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001451
sangwoo170731f2013-06-08 15:36:36 +09001452 usecase->in_snd_device = in_snd_device;
1453 usecase->out_snd_device = out_snd_device;
1454
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301455 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001456 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301457 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001458 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301459 usecase->stream.out->flags,
1460 usecase->stream.out->format,
1461 usecase->stream.out->sample_rate,
1462 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301463 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301464 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001465 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001466
1467 /* Notify device change info to effect clients registered */
1468 audio_extn_gef_notify_device_config(
1469 usecase->stream.out->devices,
1470 usecase->stream.out->channel_mask,
1471 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301472 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001473
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001475
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001476 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1477 /* Enable sidetone only if other voice/voip call already exists */
1478 if (voice_is_call_state_active(adev) ||
1479 voice_extn_compress_voip_is_started(adev))
1480 voice_set_sidetone(adev, out_snd_device, true);
1481 }
1482
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001483 /* Applicable only on the targets that has external modem.
1484 * Enable device command should be sent to modem only after
1485 * enabling voice call mixer controls
1486 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001487 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001488 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1489 out_snd_device,
1490 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301491 ALOGD("%s: done",__func__);
1492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 return status;
1494}
1495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496static int stop_input_stream(struct stream_in *in)
1497{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301498 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 struct audio_usecase *uc_info;
1500 struct audio_device *adev = in->dev;
1501
Eric Laurentc8400632013-02-14 19:04:54 -08001502 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503
Eric Laurent994a6932013-07-17 11:51:42 -07001504 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 uc_info = get_usecase_from_list(adev, in->usecase);
1507 if (uc_info == NULL) {
1508 ALOGE("%s: Could not find the usecase (%d) in the list",
1509 __func__, in->usecase);
1510 return -EINVAL;
1511 }
1512
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001513 /* Close in-call recording streams */
1514 voice_check_and_stop_incall_rec_usecase(adev, in);
1515
Eric Laurent150dbfe2013-02-27 14:31:02 -08001516 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001517 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518
1519 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001520 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001522 list_remove(&uc_info->list);
1523 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524
Eric Laurent994a6932013-07-17 11:51:42 -07001525 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 return ret;
1527}
1528
1529int start_input_stream(struct stream_in *in)
1530{
1531 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001532 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 struct audio_usecase *uc_info;
1534 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301535 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Mingming Yin2664a5b2015-09-03 10:53:11 -07001537 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1538 if (get_usecase_from_list(adev, usecase) == NULL)
1539 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301540 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1541 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001542
Naresh Tanniru80659832014-06-04 18:17:56 +05301543
1544 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301545 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301546 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301547 goto error_config;
1548 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301549
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001550 /* Check if source matches incall recording usecase criteria */
1551 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1552 if (ret)
1553 goto error_config;
1554 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001555 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1556
1557 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1558 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1559 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001560 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001561 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001562
Eric Laurentb23d5282013-05-14 15:27:20 -07001563 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 if (in->pcm_device_id < 0) {
1565 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1566 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001567 ret = -EINVAL;
1568 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570
1571 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001573
1574 if (!uc_info) {
1575 ret = -ENOMEM;
1576 goto error_config;
1577 }
1578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 uc_info->id = in->usecase;
1580 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001581 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 uc_info->devices = in->device;
1583 uc_info->in_snd_device = SND_DEVICE_NONE;
1584 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001586 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301587 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1588 adev->perf_lock_opts,
1589 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301592 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1593 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001594
1595 unsigned int flags = PCM_IN;
1596 unsigned int pcm_open_retry_count = 0;
1597
1598 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1599 flags |= PCM_MMAP | PCM_NOIRQ;
1600 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001601 } else if (in->realtime) {
1602 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001603 }
1604
1605 while (1) {
1606 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1607 flags, &in->config);
1608 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1609 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1610 if (in->pcm != NULL) {
1611 pcm_close(in->pcm);
1612 in->pcm = NULL;
1613 }
1614 if (pcm_open_retry_count-- == 0) {
1615 ret = -EIO;
1616 goto error_open;
1617 }
1618 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1619 continue;
1620 }
1621 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001623
1624 ALOGV("%s: pcm_prepare", __func__);
1625 ret = pcm_prepare(in->pcm);
1626 if (ret < 0) {
1627 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1628 pcm_close(in->pcm);
1629 in->pcm = NULL;
1630 goto error_open;
1631 }
1632
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001633 register_in_stream(in);
1634 if (in->realtime) {
1635 ret = pcm_start(in->pcm);
1636 if (ret < 0)
1637 goto error_open;
1638 }
1639
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301640 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001641 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001642
Eric Laurentc8400632013-02-14 19:04:54 -08001643 return ret;
1644
1645error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301646 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001648error_config:
1649 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301650 /*
1651 * sleep 50ms to allow sufficient time for kernel
1652 * drivers to recover incases like SSR.
1653 */
1654 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001655 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001656
1657 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658}
1659
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001660void lock_input_stream(struct stream_in *in)
1661{
1662 pthread_mutex_lock(&in->pre_lock);
1663 pthread_mutex_lock(&in->lock);
1664 pthread_mutex_unlock(&in->pre_lock);
1665}
1666
1667void lock_output_stream(struct stream_out *out)
1668{
1669 pthread_mutex_lock(&out->pre_lock);
1670 pthread_mutex_lock(&out->lock);
1671 pthread_mutex_unlock(&out->pre_lock);
1672}
1673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674/* must be called with out->lock locked */
1675static int send_offload_cmd_l(struct stream_out* out, int command)
1676{
1677 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1678
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001679 if (!cmd) {
1680 ALOGE("failed to allocate mem for command 0x%x", command);
1681 return -ENOMEM;
1682 }
1683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684 ALOGVV("%s %d", __func__, command);
1685
1686 cmd->cmd = command;
1687 list_add_tail(&out->offload_cmd_list, &cmd->node);
1688 pthread_cond_signal(&out->offload_cond);
1689 return 0;
1690}
1691
1692/* must be called iwth out->lock locked */
1693static void stop_compressed_output_l(struct stream_out *out)
1694{
1695 out->offload_state = OFFLOAD_STATE_IDLE;
1696 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001697 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001698 if (out->compr != NULL) {
1699 compress_stop(out->compr);
1700 while (out->offload_thread_blocked) {
1701 pthread_cond_wait(&out->cond, &out->lock);
1702 }
1703 }
1704}
1705
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001706bool is_offload_usecase(audio_usecase_t uc_id)
1707{
1708 unsigned int i;
1709 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1710 if (uc_id == offload_usecases[i])
1711 return true;
1712 }
1713 return false;
1714}
1715
vivek mehta446c3962015-09-14 10:57:35 -07001716static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001717{
vivek mehta446c3962015-09-14 10:57:35 -07001718 audio_usecase_t ret_uc = USECASE_INVALID;
1719 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001720 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001721 if (!adev->multi_offload_enable) {
1722 if (is_direct_pcm)
1723 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1724 else
1725 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726
vivek mehta446c3962015-09-14 10:57:35 -07001727 pthread_mutex_lock(&adev->lock);
1728 if (get_usecase_from_list(adev, ret_uc) != NULL)
1729 ret_uc = USECASE_INVALID;
1730 pthread_mutex_unlock(&adev->lock);
1731
1732 return ret_uc;
1733 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001734
1735 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001736 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1737 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1738 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1739 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001740 break;
1741 }
1742 }
vivek mehta446c3962015-09-14 10:57:35 -07001743
1744 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1745 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001746}
1747
1748static void free_offload_usecase(struct audio_device *adev,
1749 audio_usecase_t uc_id)
1750{
vivek mehta446c3962015-09-14 10:57:35 -07001751 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001752 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001753
1754 if (!adev->multi_offload_enable)
1755 return;
1756
1757 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1758 if (offload_usecases[offload_uc_index] == uc_id) {
1759 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001760 break;
1761 }
1762 }
1763 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1764}
1765
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766static void *offload_thread_loop(void *context)
1767{
1768 struct stream_out *out = (struct stream_out *) context;
1769 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001770 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1773 set_sched_policy(0, SP_FOREGROUND);
1774 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1775
1776 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001777 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 for (;;) {
1779 struct offload_cmd *cmd = NULL;
1780 stream_callback_event_t event;
1781 bool send_callback = false;
1782
1783 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1784 __func__, list_empty(&out->offload_cmd_list),
1785 out->offload_state);
1786 if (list_empty(&out->offload_cmd_list)) {
1787 ALOGV("%s SLEEPING", __func__);
1788 pthread_cond_wait(&out->offload_cond, &out->lock);
1789 ALOGV("%s RUNNING", __func__);
1790 continue;
1791 }
1792
1793 item = list_head(&out->offload_cmd_list);
1794 cmd = node_to_item(item, struct offload_cmd, node);
1795 list_remove(item);
1796
1797 ALOGVV("%s STATE %d CMD %d out->compr %p",
1798 __func__, out->offload_state, cmd->cmd, out->compr);
1799
1800 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1801 free(cmd);
1802 break;
1803 }
1804
1805 if (out->compr == NULL) {
1806 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001807 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 pthread_cond_signal(&out->cond);
1809 continue;
1810 }
1811 out->offload_thread_blocked = true;
1812 pthread_mutex_unlock(&out->lock);
1813 send_callback = false;
1814 switch(cmd->cmd) {
1815 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001816 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001818 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 send_callback = true;
1820 event = STREAM_CBK_EVENT_WRITE_READY;
1821 break;
1822 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001823 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301824 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001825 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301826 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001827 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301828 if (ret < 0)
1829 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301830 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301831 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001832 compress_drain(out->compr);
1833 else
1834 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301835 if (ret != -ENETRESET) {
1836 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301837 pthread_mutex_lock(&out->lock);
1838 out->send_new_metadata = 1;
1839 out->send_next_track_params = true;
1840 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301841 event = STREAM_CBK_EVENT_DRAIN_READY;
1842 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1843 } else
1844 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 break;
1846 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001847 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001848 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001849 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850 send_callback = true;
1851 event = STREAM_CBK_EVENT_DRAIN_READY;
1852 break;
1853 default:
1854 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1855 break;
1856 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001857 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 out->offload_thread_blocked = false;
1859 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001860 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001861 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001862 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001863 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 free(cmd);
1865 }
1866
1867 pthread_cond_signal(&out->cond);
1868 while (!list_empty(&out->offload_cmd_list)) {
1869 item = list_head(&out->offload_cmd_list);
1870 list_remove(item);
1871 free(node_to_item(item, struct offload_cmd, node));
1872 }
1873 pthread_mutex_unlock(&out->lock);
1874
1875 return NULL;
1876}
1877
1878static int create_offload_callback_thread(struct stream_out *out)
1879{
1880 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1881 list_init(&out->offload_cmd_list);
1882 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1883 offload_thread_loop, out);
1884 return 0;
1885}
1886
1887static int destroy_offload_callback_thread(struct stream_out *out)
1888{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001889 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 stop_compressed_output_l(out);
1891 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1892
1893 pthread_mutex_unlock(&out->lock);
1894 pthread_join(out->offload_thread, (void **) NULL);
1895 pthread_cond_destroy(&out->offload_cond);
1896
1897 return 0;
1898}
1899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900static int stop_output_stream(struct stream_out *out)
1901{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301902 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 struct audio_usecase *uc_info;
1904 struct audio_device *adev = out->dev;
1905
Eric Laurent994a6932013-07-17 11:51:42 -07001906 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 uc_info = get_usecase_from_list(adev, out->usecase);
1909 if (uc_info == NULL) {
1910 ALOGE("%s: Could not find the usecase (%d) in the list",
1911 __func__, out->usecase);
1912 return -EINVAL;
1913 }
1914
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001915 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301916 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001917 if (adev->visualizer_stop_output != NULL)
1918 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001919
1920 audio_extn_dts_remove_state_notifier_node(out->usecase);
1921
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001922 if (adev->offload_effects_stop_output != NULL)
1923 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1924 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001925
Eric Laurent150dbfe2013-02-27 14:31:02 -08001926 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001927 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001928
1929 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001930 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001932 list_remove(&uc_info->list);
1933 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001935 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301936 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001937 ALOGV("Disable passthrough , reset mixer to pcm");
1938 /* NO_PASSTHROUGH */
1939 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001940 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001941 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1942 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001943
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301944 /* Must be called after removing the usecase from list */
1945 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301946 audio_extn_keep_alive_start();
1947
Eric Laurent994a6932013-07-17 11:51:42 -07001948 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 return ret;
1950}
1951
1952int start_output_stream(struct stream_out *out)
1953{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 struct audio_usecase *uc_info;
1956 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301957 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001959 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1960 ret = -EINVAL;
1961 goto error_config;
1962 }
1963
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301964 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1965 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1966 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301967
Naresh Tanniru80659832014-06-04 18:17:56 +05301968 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301969 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301970 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301971 goto error_config;
1972 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301973
Eric Laurentb23d5282013-05-14 15:27:20 -07001974 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 if (out->pcm_device_id < 0) {
1976 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1977 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001978 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001979 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 }
1981
1982 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001983
1984 if (!uc_info) {
1985 ret = -ENOMEM;
1986 goto error_config;
1987 }
1988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 uc_info->id = out->usecase;
1990 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001991 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001992 uc_info->devices = out->devices;
1993 uc_info->in_snd_device = SND_DEVICE_NONE;
1994 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001995 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301997 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1998 adev->perf_lock_opts,
1999 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302000
2001 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2002 audio_extn_keep_alive_stop();
2003 if (audio_extn_passthru_is_enabled() &&
2004 audio_extn_passthru_is_passthrough_stream(out)) {
2005 audio_extn_passthru_on_start(out);
2006 audio_extn_passthru_update_stream_configuration(adev, out);
2007 }
2008 }
2009
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002010 select_devices(adev, out->usecase);
2011
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002012 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2013 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002014 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002015 unsigned int flags = PCM_OUT;
2016 unsigned int pcm_open_retry_count = 0;
2017 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2018 flags |= PCM_MMAP | PCM_NOIRQ;
2019 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002020 } else if (out->realtime) {
2021 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002022 } else
2023 flags |= PCM_MONOTONIC;
2024
2025 while (1) {
2026 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2027 flags, &out->config);
2028 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2029 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2030 if (out->pcm != NULL) {
2031 pcm_close(out->pcm);
2032 out->pcm = NULL;
2033 }
2034 if (pcm_open_retry_count-- == 0) {
2035 ret = -EIO;
2036 goto error_open;
2037 }
2038 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2039 continue;
2040 }
2041 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002043
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002044 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2045 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002046
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002047 ALOGV("%s: pcm_prepare", __func__);
2048 if (pcm_is_ready(out->pcm)) {
2049 ret = pcm_prepare(out->pcm);
2050 if (ret < 0) {
2051 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2052 pcm_close(out->pcm);
2053 out->pcm = NULL;
2054 goto error_open;
2055 }
2056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002058 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2059 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002061 out->compr = compress_open(adev->snd_card,
2062 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 COMPRESS_IN, &out->compr_config);
2064 if (out->compr && !is_compress_ready(out->compr)) {
2065 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2066 compress_close(out->compr);
2067 out->compr = NULL;
2068 ret = -EIO;
2069 goto error_open;
2070 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302071 /* compress_open sends params of the track, so reset the flag here */
2072 out->is_compr_metadata_avail = false;
2073
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 if (out->offload_callback)
2075 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002076
Fred Oh3f43e742015-03-04 18:42:34 -08002077 /* Since small bufs uses blocking writes, a write will be blocked
2078 for the default max poll time (20s) in the event of an SSR.
2079 Reduce the poll time to observe and deal with SSR faster.
2080 */
Ashish Jain5106d362016-05-11 19:23:33 +05302081 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002082 compress_set_max_poll_wait(out->compr, 1000);
2083 }
2084
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002085 audio_extn_dts_create_state_notifier_node(out->usecase);
2086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2087 popcount(out->channel_mask),
2088 out->playback_started);
2089
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002090#ifdef DS1_DOLBY_DDP_ENABLED
2091 if (audio_extn_is_dolby_format(out->format))
2092 audio_extn_dolby_send_ddp_endp_params(adev);
2093#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302094 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002095 if (adev->visualizer_start_output != NULL)
2096 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2097 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302098 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002099 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002100 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002102
2103 if (ret == 0) {
2104 register_out_stream(out);
2105 if (out->realtime) {
2106 ret = pcm_start(out->pcm);
2107 if (ret < 0)
2108 goto error_open;
2109 }
2110 }
2111
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302112 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002113 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002114
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002115 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302117 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002119error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302120 /*
2121 * sleep 50ms to allow sufficient time for kernel
2122 * drivers to recover incases like SSR.
2123 */
2124 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002125 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126}
2127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128static int check_input_parameters(uint32_t sample_rate,
2129 audio_format_t format,
2130 int channel_count)
2131{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002132 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302134 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2135 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2136 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002137 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302138 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002139
2140 switch (channel_count) {
2141 case 1:
2142 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302143 case 3:
2144 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002145 case 6:
2146 break;
2147 default:
2148 ret = -EINVAL;
2149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
2151 switch (sample_rate) {
2152 case 8000:
2153 case 11025:
2154 case 12000:
2155 case 16000:
2156 case 22050:
2157 case 24000:
2158 case 32000:
2159 case 44100:
2160 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302161 case 96000:
2162 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 break;
2164 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002165 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002168 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169}
2170
2171static size_t get_input_buffer_size(uint32_t sample_rate,
2172 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002173 int channel_count,
2174 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175{
2176 size_t size = 0;
2177
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002178 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2179 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002181 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002182 if (is_low_latency)
2183 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302184
2185 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002187 /* make sure the size is multiple of 32 bytes
2188 * At 48 kHz mono 16-bit PCM:
2189 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2190 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2191 */
2192 size += 0x1f;
2193 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002194
2195 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196}
2197
Ashish Jain5106d362016-05-11 19:23:33 +05302198static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2199{
2200 uint64_t actual_frames_rendered = 0;
2201 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2202
2203 /* This adjustment accounts for buffering after app processor.
2204 * It is based on estimated DSP latency per use case, rather than exact.
2205 */
2206 int64_t platform_latency = platform_render_latency(out->usecase) *
2207 out->sample_rate / 1000000LL;
2208
2209 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2210 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2211 * hence only estimate.
2212 */
2213 int64_t signed_frames = out->written - kernel_buffer_size;
2214
2215 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2216
2217 if (signed_frames > 0)
2218 actual_frames_rendered = signed_frames;
2219
2220 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2221 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2222 (long long int)out->written, (int)kernel_buffer_size,
2223 audio_bytes_per_sample(out->compr_config.codec->format),
2224 popcount(out->channel_mask));
2225
2226 return actual_frames_rendered;
2227}
2228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2230{
2231 struct stream_out *out = (struct stream_out *)stream;
2232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234}
2235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002236static int out_set_sample_rate(struct audio_stream *stream __unused,
2237 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238{
2239 return -ENOSYS;
2240}
2241
2242static size_t out_get_buffer_size(const struct audio_stream *stream)
2243{
2244 struct stream_out *out = (struct stream_out *)stream;
2245
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002246 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002248 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2249 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302250 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302251 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002253 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002254 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255}
2256
2257static uint32_t out_get_channels(const struct audio_stream *stream)
2258{
2259 struct stream_out *out = (struct stream_out *)stream;
2260
2261 return out->channel_mask;
2262}
2263
2264static audio_format_t out_get_format(const struct audio_stream *stream)
2265{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 struct stream_out *out = (struct stream_out *)stream;
2267
2268 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269}
2270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002271static int out_set_format(struct audio_stream *stream __unused,
2272 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273{
2274 return -ENOSYS;
2275}
2276
2277static int out_standby(struct audio_stream *stream)
2278{
2279 struct stream_out *out = (struct stream_out *)stream;
2280 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302282 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2283 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002285 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002287 if (adev->adm_deregister_stream)
2288 adev->adm_deregister_stream(adev->adm_data, out->handle);
2289
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002290 if (is_offload_usecase(out->usecase))
2291 stop_compressed_output_l(out);
2292
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002293 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002295 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2296 voice_extn_compress_voip_close_output_stream(stream);
2297 pthread_mutex_unlock(&adev->lock);
2298 pthread_mutex_unlock(&out->lock);
2299 ALOGD("VOIP output entered standby");
2300 return 0;
2301 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 if (out->pcm) {
2303 pcm_close(out->pcm);
2304 out->pcm = NULL;
2305 }
2306 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002307 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302308 out->send_next_track_params = false;
2309 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002310 out->gapless_mdata.encoder_delay = 0;
2311 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312 if (out->compr != NULL) {
2313 compress_close(out->compr);
2314 out->compr = NULL;
2315 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002316 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002318 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 }
2320 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302321 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 return 0;
2323}
2324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002325static int out_dump(const struct audio_stream *stream __unused,
2326 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327{
2328 return 0;
2329}
2330
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002331static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2332{
2333 int ret = 0;
2334 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002335
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002336 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002337 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002338 return -EINVAL;
2339 }
2340
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302341 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002342
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002343 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2344 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302345 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002346 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002347 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2348 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302349 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002350 }
2351
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002352 ALOGV("%s new encoder delay %u and padding %u", __func__,
2353 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2354
2355 return 0;
2356}
2357
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002358static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2359{
2360 return out == adev->primary_output || out == adev->voice_tx_output;
2361}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 struct audio_device *adev = out->dev;
2367 struct str_parms *parms;
2368 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002369 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370
sangwoobc677242013-08-08 16:53:43 +09002371 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002372 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302374 if (!parms)
2375 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002376 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2377 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002379 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002380 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002382 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002383 * When HDMI cable is unplugged the music playback is paused and
2384 * the policy manager sends routing=0. But the audioflinger continues
2385 * to write data until standby time (3sec). As the HDMI core is
2386 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002387 * Avoid this by routing audio to speaker until standby.
2388 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002389 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2390 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302391 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002392 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2393 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302395 /*
2396 * When A2DP is disconnected the
2397 * music playback is paused and the policy manager sends routing=0
2398 * But the audioflingercontinues to write data until standby time
2399 * (3sec). As BT is turned off, the write gets blocked.
2400 * Avoid this by routing audio to speaker until standby.
2401 */
2402 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2403 (val == AUDIO_DEVICE_NONE)) {
2404 val = AUDIO_DEVICE_OUT_SPEAKER;
2405 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002406
2407 /*
2408 * select_devices() call below switches all the usecases on the same
2409 * backend to the new device. Refer to check_usecases_codec_backend() in
2410 * the select_devices(). But how do we undo this?
2411 *
2412 * For example, music playback is active on headset (deep-buffer usecase)
2413 * and if we go to ringtones and select a ringtone, low-latency usecase
2414 * will be started on headset+speaker. As we can't enable headset+speaker
2415 * and headset devices at the same time, select_devices() switches the music
2416 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2417 * So when the ringtone playback is completed, how do we undo the same?
2418 *
2419 * We are relying on the out_set_parameters() call on deep-buffer output,
2420 * once the ringtone playback is ended.
2421 * NOTE: We should not check if the current devices are same as new devices.
2422 * Because select_devices() must be called to switch back the music
2423 * playback to headset.
2424 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002425 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002426 audio_devices_t new_dev = val;
2427 bool same_dev = out->devices == new_dev;
2428 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002429
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002430 if (output_drives_call(adev, out)) {
2431 if(!voice_is_in_call(adev)) {
2432 if (adev->mode == AUDIO_MODE_IN_CALL) {
2433 adev->current_call_output = out;
2434 ret = voice_start_call(adev);
2435 }
2436 } else {
2437 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002438 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002439 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002440 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002441
2442 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002443 if (!same_dev) {
2444 ALOGV("update routing change");
2445 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302446 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2447 adev->perf_lock_opts,
2448 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002449 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002450 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302451 if (!same_dev)
2452 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002453 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002454 }
2455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002457 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002459
2460 if (out == adev->primary_output) {
2461 pthread_mutex_lock(&adev->lock);
2462 audio_extn_set_parameters(adev, parms);
2463 pthread_mutex_unlock(&adev->lock);
2464 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002465 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002466 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002467 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002468
2469 audio_extn_dts_create_state_notifier_node(out->usecase);
2470 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2471 popcount(out->channel_mask),
2472 out->playback_started);
2473
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002474 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002475 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302478error:
Eric Laurent994a6932013-07-17 11:51:42 -07002479 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 return ret;
2481}
2482
2483static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2484{
2485 struct stream_out *out = (struct stream_out *)stream;
2486 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002487 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 char value[256];
2489 struct str_parms *reply = str_parms_create();
2490 size_t i, j;
2491 int ret;
2492 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002493
2494 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002495 if (reply) {
2496 str_parms_destroy(reply);
2497 }
2498 if (query) {
2499 str_parms_destroy(query);
2500 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002501 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2502 return NULL;
2503 }
2504
Eric Laurent994a6932013-07-17 11:51:42 -07002505 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2507 if (ret >= 0) {
2508 value[0] = '\0';
2509 i = 0;
2510 while (out->supported_channel_masks[i] != 0) {
2511 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2512 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2513 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002514 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002516 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 first = false;
2518 break;
2519 }
2520 }
2521 i++;
2522 }
2523 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2524 str = str_parms_to_str(reply);
2525 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002526 voice_extn_out_get_parameters(out, query, reply);
2527 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002528 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002529 free(str);
2530 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002531 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002533
Alexy Joseph62142aa2015-11-16 15:10:34 -08002534
2535 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2536 if (ret >= 0) {
2537 value[0] = '\0';
2538 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2539 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302540 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002541 } else {
2542 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302543 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002544 }
2545 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002546 if (str)
2547 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002548 str = str_parms_to_str(reply);
2549 }
2550
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002551 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2552 if (ret >= 0) {
2553 value[0] = '\0';
2554 i = 0;
2555 first = true;
2556 while (out->supported_formats[i] != 0) {
2557 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2558 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2559 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002560 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002561 }
2562 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2563 first = false;
2564 break;
2565 }
2566 }
2567 i++;
2568 }
2569 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002570 if (str)
2571 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002572 str = str_parms_to_str(reply);
2573 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002574
2575 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2576 if (ret >= 0) {
2577 value[0] = '\0';
2578 i = 0;
2579 first = true;
2580 while (out->supported_sample_rates[i] != 0) {
2581 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2582 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2583 if (!first) {
2584 strlcat(value, "|", sizeof(value));
2585 }
2586 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2587 first = false;
2588 break;
2589 }
2590 }
2591 i++;
2592 }
2593 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2594 if (str)
2595 free(str);
2596 str = str_parms_to_str(reply);
2597 }
2598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 str_parms_destroy(query);
2600 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002601 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 return str;
2603}
2604
2605static uint32_t out_get_latency(const struct audio_stream_out *stream)
2606{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002607 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002609 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610
Alexy Josephaa54c872014-12-03 02:46:47 -08002611 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002612 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002613 } else if (out->realtime) {
2614 // since the buffer won't be filled up faster than realtime,
2615 // return a smaller number
2616 if (out->config.rate)
2617 period_ms = (out->af_period_multiplier * out->config.period_size *
2618 1000) / (out->config.rate);
2619 else
2620 period_ms = 0;
2621 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002622 } else {
2623 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002625 }
2626
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302627 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002628 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629}
2630
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302631static float AmpToDb(float amplification)
2632{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302633 float db = DSD_VOLUME_MIN_DB;
2634 if (amplification > 0) {
2635 db = 20 * log10(amplification);
2636 if(db < DSD_VOLUME_MIN_DB)
2637 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302638 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302639 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302640}
2641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642static int out_set_volume(struct audio_stream_out *stream, float left,
2643 float right)
2644{
Eric Laurenta9024de2013-04-04 09:19:12 -07002645 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002646 int volume[2];
2647
Eric Laurenta9024de2013-04-04 09:19:12 -07002648 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2649 /* only take left channel into account: the API is for stereo anyway */
2650 out->muted = (left == 0.0f);
2651 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002652 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302653 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002654 /*
2655 * Set mute or umute on HDMI passthrough stream.
2656 * Only take left channel into account.
2657 * Mute is 0 and unmute 1
2658 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302659 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302660 } else if (out->format == AUDIO_FORMAT_DSD){
2661 char mixer_ctl_name[128] = "DSD Volume";
2662 struct audio_device *adev = out->dev;
2663 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2664
2665 if (!ctl) {
2666 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2667 __func__, mixer_ctl_name);
2668 return -EINVAL;
2669 }
2670 volume[0] = (int)(AmpToDb(left));
2671 volume[1] = (int)(AmpToDb(right));
2672 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2673 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002674 } else {
2675 char mixer_ctl_name[128];
2676 struct audio_device *adev = out->dev;
2677 struct mixer_ctl *ctl;
2678 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002679 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002681 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2682 "Compress Playback %d Volume", pcm_device_id);
2683 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2684 if (!ctl) {
2685 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2686 __func__, mixer_ctl_name);
2687 return -EINVAL;
2688 }
2689 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2690 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2691 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2692 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002693 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002694 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 return -ENOSYS;
2697}
2698
2699static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2700 size_t bytes)
2701{
2702 struct stream_out *out = (struct stream_out *)stream;
2703 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302704 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002705 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002707 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302708
Naresh Tanniru80659832014-06-04 18:17:56 +05302709 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002710
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302711 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302712 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302713 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2714 pthread_mutex_unlock(&out->lock);
2715 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302716 } else {
2717 /* increase written size during SSR to avoid mismatch
2718 * with the written frames count in AF
2719 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002720 // bytes per frame
2721 size_t bpf = audio_bytes_per_sample(out->format) *
2722 audio_channel_count_from_out_mask(out->channel_mask);
2723 if (bpf != 0)
2724 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302725 ALOGD(" %s: sound card is not active/SSR state", __func__);
2726 ret= -EIO;
2727 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302728 }
2729 }
2730
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302731 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302732 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2733 if (audio_bytes_per_sample(out->format) != 0)
2734 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2735 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302736 goto exit;
2737 }
2738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002740 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002741 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002742 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2743 ret = voice_extn_compress_voip_start_output_stream(out);
2744 else
2745 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002746 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002747 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002749 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 goto exit;
2751 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002752
2753 if (last_known_cal_step != -1) {
2754 ALOGD("%s: retry previous failed cal level set", __func__);
2755 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758
Ashish Jain81eb2a82015-05-13 10:52:34 +05302759 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002760 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302761 adev->is_channel_status_set = true;
2762 }
2763
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002764 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002765 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002766 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002767 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002768 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2769 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302770 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2771 ALOGD("copl(%p):send next track params in gapless", out);
2772 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2773 out->send_next_track_params = false;
2774 out->is_compr_metadata_avail = false;
2775 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002776 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302777 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302778 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002779
Ashish Jain83a6cc22016-06-28 14:34:17 +05302780 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302781 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302782 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302783 pthread_mutex_unlock(&out->lock);
2784 return -EINVAL;
2785 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302786 audio_format_t dst_format = out->hal_op_format;
2787 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302788
2789 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2790 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2791
Ashish Jain83a6cc22016-06-28 14:34:17 +05302792 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302793 dst_format,
2794 buffer,
2795 src_format,
2796 frames);
2797
Ashish Jain83a6cc22016-06-28 14:34:17 +05302798 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302799 bytes_to_write);
2800
2801 /*Convert written bytes in audio flinger format*/
2802 if (ret > 0)
2803 ret = ((ret * format_to_bitwidth_table[out->format]) /
2804 format_to_bitwidth_table[dst_format]);
2805 }
2806 } else
2807 ret = compress_write(out->compr, buffer, bytes);
2808
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302809 if (ret < 0)
2810 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302811 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302812 /*msg to cb thread only if non blocking write is enabled*/
2813 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302814 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302816 } else if (-ENETRESET == ret) {
2817 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2818 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2819 pthread_mutex_unlock(&out->lock);
2820 out_standby(&out->stream.common);
2821 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 }
Ashish Jain5106d362016-05-11 19:23:33 +05302823 if ( ret == (ssize_t)bytes && !out->non_blocking)
2824 out->written += bytes;
2825
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302826 /* Call compr start only when non-zero bytes of data is there to be rendered */
2827 if (!out->playback_started && ret > 0) {
2828 int status = compress_start(out->compr);
2829 if (status < 0) {
2830 ret = status;
2831 ALOGE("%s: compr start failed with err %d", __func__, errno);
2832 goto exit;
2833 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002834 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 out->playback_started = 1;
2836 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002837
2838 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2839 popcount(out->channel_mask),
2840 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 }
2842 pthread_mutex_unlock(&out->lock);
2843 return ret;
2844 } else {
2845 if (out->pcm) {
2846 if (out->muted)
2847 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002848
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302849 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002850
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002851 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002852
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002853 if (out->config.rate)
2854 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2855 out->config.rate;
2856
2857 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2858
2859 request_out_focus(out, ns);
2860
2861 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002862 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002863 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302864 out->convert_buffer != NULL) {
2865
2866 memcpy_by_audio_format(out->convert_buffer,
2867 out->hal_op_format,
2868 buffer,
2869 out->hal_ip_format,
2870 out->config.period_size * out->config.channels);
2871
2872 ret = pcm_write(out->pcm, out->convert_buffer,
2873 (out->config.period_size *
2874 out->config.channels *
2875 format_to_bitwidth_table[out->hal_op_format]));
2876 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002877 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302878 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002879
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002880 release_out_focus(out);
2881
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302882 if (ret < 0)
2883 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302884 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2885 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2886 else
2887 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 }
2890
2891exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302892 /* ToDo: There may be a corner case when SSR happens back to back during
2893 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302894 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302895 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302896 }
2897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 pthread_mutex_unlock(&out->lock);
2899
2900 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002901 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002902 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302903 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302904 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302905 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302906 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302907 out->standby = true;
2908 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302910 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2911 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2912 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
2914 return bytes;
2915}
2916
2917static int out_get_render_position(const struct audio_stream_out *stream,
2918 uint32_t *dsp_frames)
2919{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302921 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002922
2923 if (dsp_frames == NULL)
2924 return -EINVAL;
2925
2926 *dsp_frames = 0;
2927 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002928 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302929
2930 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2931 * this operation and adev_close_output_stream(where out gets reset).
2932 */
2933 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2934 *dsp_frames = get_actual_pcm_frames_rendered(out);
2935 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2936 return 0;
2937 }
2938
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002939 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302940 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302941 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302943 if (ret < 0)
2944 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302946 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 }
2948 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302949 if (-ENETRESET == ret) {
2950 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2951 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2952 return -EINVAL;
2953 } else if(ret < 0) {
2954 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2955 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302956 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2957 /*
2958 * Handle corner case where compress session is closed during SSR
2959 * and timestamp is queried
2960 */
2961 ALOGE(" ERROR: sound card not active, return error");
2962 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302963 } else {
2964 return 0;
2965 }
Zhou Song32a556e2015-05-05 10:46:56 +08002966 } else if (audio_is_linear_pcm(out->format)) {
2967 *dsp_frames = out->written;
2968 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 } else
2970 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971}
2972
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002973static int out_add_audio_effect(const struct audio_stream *stream __unused,
2974 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975{
2976 return 0;
2977}
2978
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002979static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2980 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981{
2982 return 0;
2983}
2984
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002985static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2986 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987{
2988 return -EINVAL;
2989}
2990
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002991static int out_get_presentation_position(const struct audio_stream_out *stream,
2992 uint64_t *frames, struct timespec *timestamp)
2993{
2994 struct stream_out *out = (struct stream_out *)stream;
2995 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002996 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002997
Ashish Jain5106d362016-05-11 19:23:33 +05302998 /* below piece of code is not guarded against any lock because audioFliner serializes
2999 * this operation and adev_close_output_stream( where out gets reset).
3000 */
3001 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3002 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3003 *frames = get_actual_pcm_frames_rendered(out);
3004 /* this is the best we can do */
3005 clock_gettime(CLOCK_MONOTONIC, timestamp);
3006 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3007 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3008 return 0;
3009 }
3010
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003011 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003012
Ashish Jain5106d362016-05-11 19:23:33 +05303013 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3014 ret = compress_get_tstamp(out->compr, &dsp_frames,
3015 &out->sample_rate);
3016 ALOGVV("%s rendered frames %ld sample_rate %d",
3017 __func__, dsp_frames, out->sample_rate);
3018 *frames = dsp_frames;
3019 if (ret < 0)
3020 ret = -errno;
3021 if (-ENETRESET == ret) {
3022 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3023 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3024 ret = -EINVAL;
3025 } else
3026 ret = 0;
3027 /* this is the best we can do */
3028 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003029 } else {
3030 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003031 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003032 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3033 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003034 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003035 // This adjustment accounts for buffering after app processor.
3036 // It is based on estimated DSP latency per use case, rather than exact.
3037 signed_frames -=
3038 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3039
Eric Laurent949a0892013-09-20 09:20:13 -07003040 // It would be unusual for this value to be negative, but check just in case ...
3041 if (signed_frames >= 0) {
3042 *frames = signed_frames;
3043 ret = 0;
3044 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003045 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303046 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3047 *frames = out->written;
3048 clock_gettime(CLOCK_MONOTONIC, timestamp);
3049 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050 }
3051 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003052 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003053 return ret;
3054}
3055
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056static int out_set_callback(struct audio_stream_out *stream,
3057 stream_callback_t callback, void *cookie)
3058{
3059 struct stream_out *out = (struct stream_out *)stream;
3060
3061 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003062 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 out->offload_callback = callback;
3064 out->offload_cookie = cookie;
3065 pthread_mutex_unlock(&out->lock);
3066 return 0;
3067}
3068
3069static int out_pause(struct audio_stream_out* stream)
3070{
3071 struct stream_out *out = (struct stream_out *)stream;
3072 int status = -ENOSYS;
3073 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003074 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003075 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003076 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303078 struct audio_device *adev = out->dev;
3079 int snd_scard_state = get_snd_card_state(adev);
3080
3081 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3082 status = compress_pause(out->compr);
3083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003085
Mingming Yin21854652016-04-13 11:54:02 -07003086 if (audio_extn_passthru_is_active()) {
3087 ALOGV("offload use case, pause passthru");
3088 audio_extn_passthru_on_pause(out);
3089 }
3090
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303091 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003092 audio_extn_dts_notify_playback_state(out->usecase, 0,
3093 out->sample_rate, popcount(out->channel_mask),
3094 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 }
3096 pthread_mutex_unlock(&out->lock);
3097 }
3098 return status;
3099}
3100
3101static int out_resume(struct audio_stream_out* stream)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 int status = -ENOSYS;
3105 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003106 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003107 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003109 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303111 struct audio_device *adev = out->dev;
3112 int snd_scard_state = get_snd_card_state(adev);
3113
Mingming Yin21854652016-04-13 11:54:02 -07003114 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3115 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3116 pthread_mutex_lock(&out->dev->lock);
3117 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003118 pthread_mutex_unlock(&out->dev->lock);
3119 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303120 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003121 }
3122 if (!status) {
3123 out->offload_state = OFFLOAD_STATE_PLAYING;
3124 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303125 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003126 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3127 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 }
3129 pthread_mutex_unlock(&out->lock);
3130 }
3131 return status;
3132}
3133
3134static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3135{
3136 struct stream_out *out = (struct stream_out *)stream;
3137 int status = -ENOSYS;
3138 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003139 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003140 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003141 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3142 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3143 else
3144 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3145 pthread_mutex_unlock(&out->lock);
3146 }
3147 return status;
3148}
3149
3150static int out_flush(struct audio_stream_out* stream)
3151{
3152 struct stream_out *out = (struct stream_out *)stream;
3153 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003154 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003155 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003156 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003157 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3158 stop_compressed_output_l(out);
3159 out->written = 0;
3160 } else {
3161 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3162 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003164 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 return 0;
3166 }
3167 return -ENOSYS;
3168}
3169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170/** audio_stream_in implementation **/
3171static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3172{
3173 struct stream_in *in = (struct stream_in *)stream;
3174
3175 return in->config.rate;
3176}
3177
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003178static int in_set_sample_rate(struct audio_stream *stream __unused,
3179 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
3181 return -ENOSYS;
3182}
3183
3184static size_t in_get_buffer_size(const struct audio_stream *stream)
3185{
3186 struct stream_in *in = (struct stream_in *)stream;
3187
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003188 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3189 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003190 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3191 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003192
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003193 return in->config.period_size * in->af_period_multiplier *
3194 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195}
3196
3197static uint32_t in_get_channels(const struct audio_stream *stream)
3198{
3199 struct stream_in *in = (struct stream_in *)stream;
3200
3201 return in->channel_mask;
3202}
3203
3204static audio_format_t in_get_format(const struct audio_stream *stream)
3205{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003206 struct stream_in *in = (struct stream_in *)stream;
3207
3208 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209}
3210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003211static int in_set_format(struct audio_stream *stream __unused,
3212 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213{
3214 return -ENOSYS;
3215}
3216
3217static int in_standby(struct audio_stream *stream)
3218{
3219 struct stream_in *in = (struct stream_in *)stream;
3220 struct audio_device *adev = in->dev;
3221 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303222 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3223 stream, in->usecase, use_case_table[in->usecase]);
3224
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003225 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003226 if (!in->standby && in->is_st_session) {
3227 ALOGD("%s: sound trigger pcm stop lab", __func__);
3228 audio_extn_sound_trigger_stop_lab(in);
3229 in->standby = 1;
3230 }
3231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003233 if (adev->adm_deregister_stream)
3234 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3235
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003236 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003238 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3239 voice_extn_compress_voip_close_input_stream(stream);
3240 ALOGD("VOIP input entered standby");
3241 } else {
3242 if (in->pcm) {
3243 pcm_close(in->pcm);
3244 in->pcm = NULL;
3245 }
3246 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003247 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003248 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 }
3250 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003251 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 return status;
3253}
3254
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003255static int in_dump(const struct audio_stream *stream __unused,
3256 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 return 0;
3259}
3260
3261static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3262{
3263 struct stream_in *in = (struct stream_in *)stream;
3264 struct audio_device *adev = in->dev;
3265 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003267 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303269 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 parms = str_parms_create_str(kvpairs);
3271
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303272 if (!parms)
3273 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003274 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003275 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003276
3277 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3278 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 val = atoi(value);
3280 /* no audio source uses val == 0 */
3281 if ((in->source != val) && (val != 0)) {
3282 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003283 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3284 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3285 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003286 (in->config.rate == 8000 || in->config.rate == 16000 ||
3287 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003288 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003289 err = voice_extn_compress_voip_open_input_stream(in);
3290 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003291 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003292 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003293 }
3294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296 }
3297
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003298 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3299 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003301 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 in->device = val;
3303 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003304 if (!in->standby && !in->is_st_session) {
3305 ALOGV("update input routing change");
3306 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003307 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 }
3310 }
3311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003313 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314
3315 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303316error:
Eric Laurent994a6932013-07-17 11:51:42 -07003317 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 return ret;
3319}
3320
3321static char* in_get_parameters(const struct audio_stream *stream,
3322 const char *keys)
3323{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003324 struct stream_in *in = (struct stream_in *)stream;
3325 struct str_parms *query = str_parms_create_str(keys);
3326 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003327 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003328
3329 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003330 if (reply) {
3331 str_parms_destroy(reply);
3332 }
3333 if (query) {
3334 str_parms_destroy(query);
3335 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003336 ALOGE("in_get_parameters: failed to create query or reply");
3337 return NULL;
3338 }
3339
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003340 ALOGV("%s: enter: keys - %s", __func__, keys);
3341
3342 voice_extn_in_get_parameters(in, query, reply);
3343
3344 str = str_parms_to_str(reply);
3345 str_parms_destroy(query);
3346 str_parms_destroy(reply);
3347
3348 ALOGV("%s: exit: returns - %s", __func__, str);
3349 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350}
3351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003352static int in_set_gain(struct audio_stream_in *stream __unused,
3353 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354{
3355 return 0;
3356}
3357
3358static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3359 size_t bytes)
3360{
3361 struct stream_in *in = (struct stream_in *)stream;
3362 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303363 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303364 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303365 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003367 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303368
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003369 if (in->is_st_session) {
3370 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3371 /* Read from sound trigger HAL */
3372 audio_extn_sound_trigger_read(in, buffer, bytes);
3373 pthread_mutex_unlock(&in->lock);
3374 return bytes;
3375 }
3376
Ashish Jainbbce4322016-02-16 13:25:27 +05303377 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003378 ALOGD(" %s: sound card is not active/SSR state", __func__);
3379 ret= -EIO;;
3380 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303381 }
3382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003384 pthread_mutex_lock(&adev->lock);
3385 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3386 ret = voice_extn_compress_voip_start_input_stream(in);
3387 else
3388 ret = start_input_stream(in);
3389 pthread_mutex_unlock(&adev->lock);
3390 if (ret != 0) {
3391 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 }
3393 in->standby = 0;
3394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003396 // what's the duration requested by the client?
3397 long ns = 0;
3398
3399 if (in->config.rate)
3400 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3401 in->config.rate;
3402
3403 request_in_focus(in, ns);
3404 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303407 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003408 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303409 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003410 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003411 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003412 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303413 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003414 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303415 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3416 if (bytes % 4 == 0) {
3417 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3418 int_buf_stream = buffer;
3419 for (size_t itt=0; itt < bytes/4 ; itt++) {
3420 int_buf_stream[itt] >>= 8;
3421 }
3422 } else {
3423 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3424 ret = -EINVAL;
3425 goto exit;
3426 }
3427 } if (ret < 0) {
3428 ret = -errno;
3429 }
3430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 }
3432
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003433 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 /*
3436 * Instead of writing zeroes here, we could trust the hardware
3437 * to always provide zeroes when muted.
3438 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303439 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3440 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 memset(buffer, 0, bytes);
3442
3443exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303444 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303445 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003446 if (-ENETRESET == ret)
3447 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 pthread_mutex_unlock(&in->lock);
3450
3451 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303452 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303453 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303454 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303455 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303456 in->standby = true;
3457 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303458 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003460 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303461 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303462 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 }
3464 return bytes;
3465}
3466
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003467static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468{
3469 return 0;
3470}
3471
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003472static int add_remove_audio_effect(const struct audio_stream *stream,
3473 effect_handle_t effect,
3474 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003476 struct stream_in *in = (struct stream_in *)stream;
3477 int status = 0;
3478 effect_descriptor_t desc;
3479
3480 status = (*effect)->get_descriptor(effect, &desc);
3481 if (status != 0)
3482 return status;
3483
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003484 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003485 pthread_mutex_lock(&in->dev->lock);
3486 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3487 in->enable_aec != enable &&
3488 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3489 in->enable_aec = enable;
3490 if (!in->standby)
3491 select_devices(in->dev, in->usecase);
3492 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003493 if (in->enable_ns != enable &&
3494 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3495 in->enable_ns = enable;
3496 if (!in->standby)
3497 select_devices(in->dev, in->usecase);
3498 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003499 pthread_mutex_unlock(&in->dev->lock);
3500 pthread_mutex_unlock(&in->lock);
3501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 return 0;
3503}
3504
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003505static int in_add_audio_effect(const struct audio_stream *stream,
3506 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507{
Eric Laurent994a6932013-07-17 11:51:42 -07003508 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003509 return add_remove_audio_effect(stream, effect, true);
3510}
3511
3512static int in_remove_audio_effect(const struct audio_stream *stream,
3513 effect_handle_t effect)
3514{
Eric Laurent994a6932013-07-17 11:51:42 -07003515 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003516 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517}
3518
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303519int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 audio_io_handle_t handle,
3521 audio_devices_t devices,
3522 audio_output_flags_t flags,
3523 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003524 struct audio_stream_out **stream_out,
3525 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526{
3527 struct audio_device *adev = (struct audio_device *)dev;
3528 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303529 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003530 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303533
3534 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3535 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003536 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303537 return -EINVAL;
3538 }
3539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3541
Mingming Yin3a941d42016-02-17 18:08:05 -08003542 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3543 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303544 devices, flags, &out->stream);
3545
3546
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003547 if (!out) {
3548 return -ENOMEM;
3549 }
3550
Haynes Mathew George204045b2015-02-25 20:32:03 -08003551 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003552 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003553 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 if (devices == AUDIO_DEVICE_NONE)
3556 devices = AUDIO_DEVICE_OUT_SPEAKER;
3557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 out->flags = flags;
3559 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003560 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003561 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562 out->sample_rate = config->sample_rate;
3563 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3564 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003565 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003566 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003567 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303568 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569
Mingming Yin3a941d42016-02-17 18:08:05 -08003570 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3571 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3572 pthread_mutex_lock(&adev->lock);
3573 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3574 ret = read_hdmi_sink_caps(out);
3575 pthread_mutex_unlock(&adev->lock);
3576 if (ret != 0) {
3577 if (ret == -ENOSYS) {
3578 /* ignore and go with default */
3579 ret = 0;
3580 } else {
3581 ALOGE("error reading hdmi sink caps");
3582 goto error_open;
3583 }
3584 }
3585 }
3586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003588 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303589 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3590 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003591 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3592 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3593
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003594 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003595 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3596 /*
3597 * Do not handle stereo output in Multi-channel cases
3598 * Stereo case is handled in normal playback path
3599 */
3600 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3601 ret = AUDIO_CHANNEL_OUT_STEREO;
3602 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003603
3604 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3605 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003606 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003607 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003608 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003609
3610 if (config->sample_rate == 0)
3611 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3612 if (config->channel_mask == 0)
3613 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003614 if (config->format == 0)
3615 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003616
3617 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003618 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003619 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3621 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003623 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003625 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3626 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003627 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003628 ret = voice_extn_compress_voip_open_output_stream(out);
3629 if (ret != 0) {
3630 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3631 __func__, ret);
3632 goto error_open;
3633 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003634 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3635 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3636
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003637 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3638 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3639 ALOGE("%s: Unsupported Offload information", __func__);
3640 ret = -EINVAL;
3641 goto error_open;
3642 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003643
Mingming Yin3a941d42016-02-17 18:08:05 -08003644 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003645 if(config->offload_info.format == 0)
3646 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003647 if (config->offload_info.sample_rate == 0)
3648 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003649 }
3650
Mingming Yin90310102013-11-13 16:57:00 -08003651 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303652 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003653 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 ret = -EINVAL;
3655 goto error_open;
3656 }
3657
3658 out->compr_config.codec = (struct snd_codec *)
3659 calloc(1, sizeof(struct snd_codec));
3660
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003661 if (!out->compr_config.codec) {
3662 ret = -ENOMEM;
3663 goto error_open;
3664 }
3665
vivek mehta0ea887a2015-08-26 14:01:20 -07003666 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303667 out->stream.pause = out_pause;
3668 out->stream.flush = out_flush;
3669 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003670 out->usecase = get_offload_usecase(adev, true);
3671 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003672 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003673 out->stream.set_callback = out_set_callback;
3674 out->stream.pause = out_pause;
3675 out->stream.resume = out_resume;
3676 out->stream.drain = out_drain;
3677 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003678 out->usecase = get_offload_usecase(adev, false);
3679 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003680 }
vivek mehta446c3962015-09-14 10:57:35 -07003681
3682 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003683 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3684 config->format == 0 && config->sample_rate == 0 &&
3685 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003686 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003687 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3688 } else {
3689 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3690 ret = -EEXIST;
3691 goto error_open;
3692 }
vivek mehta446c3962015-09-14 10:57:35 -07003693 }
3694
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003695 if (config->offload_info.channel_mask)
3696 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003697 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003699 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003700 } else {
3701 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3702 ret = -EINVAL;
3703 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003704 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003705
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003706 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003707 out->sample_rate = config->offload_info.sample_rate;
3708
Mingming Yin3ee55c62014-08-04 14:23:35 -07003709 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003710
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303711 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3712 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3713 audio_extn_dolby_send_ddp_endp_params(adev);
3714 audio_extn_dolby_set_dmid(adev);
3715 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003716
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003717 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003718 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 out->compr_config.codec->bit_rate =
3720 config->offload_info.bit_rate;
3721 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303722 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003723 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303724 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003725 /*TODO: Do we need to change it for passthrough */
3726 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003727
Manish Dewangana6fc5442015-08-24 20:30:31 +05303728 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3729 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3730 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3731 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303732
3733 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3734 AUDIO_FORMAT_PCM) {
3735
3736 /*Based on platform support, configure appropriate alsa format for corresponding
3737 *hal input format.
3738 */
3739 out->compr_config.codec->format = hal_format_to_alsa(
3740 config->offload_info.format);
3741
Ashish Jain83a6cc22016-06-28 14:34:17 +05303742 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303743 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303744 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303745
3746 /*for direct PCM playback populate bit_width based on selected alsa format as
3747 *hal input format and alsa format might differ based on platform support.
3748 */
3749 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303750 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303751
3752 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3753
3754 /* Check if alsa session is configured with the same format as HAL input format,
3755 * if not then derive correct fragment size needed to accomodate the
3756 * conversion of HAL input format to alsa format.
3757 */
3758 audio_extn_utils_update_direct_pcm_fragment_size(out);
3759
3760 /*if hal input and output fragment size is different this indicates HAL input format is
3761 *not same as the alsa format
3762 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303763 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303764 /*Allocate a buffer to convert input data to the alsa configured format.
3765 *size of convert buffer is equal to the size required to hold one fragment size
3766 *worth of pcm data, this is because flinger does not write more than fragment_size
3767 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303768 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3769 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303770 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3771 ret = -ENOMEM;
3772 goto error_open;
3773 }
3774 }
3775 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3776 out->compr_config.fragment_size =
3777 audio_extn_passthru_get_buffer_size(&config->offload_info);
3778 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3779 } else {
3780 out->compr_config.fragment_size =
3781 platform_get_compress_offload_buffer_size(&config->offload_info);
3782 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3783 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003784
Amit Shekhar6f461b12014-08-01 14:52:58 -07003785 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303786 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003788 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3789 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003790
Alexy Josephaa54c872014-12-03 02:46:47 -08003791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003792 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303793 out->send_next_track_params = false;
3794 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003795 out->offload_state = OFFLOAD_STATE_IDLE;
3796 out->playback_started = 0;
3797
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003798 audio_extn_dts_create_state_notifier_node(out->usecase);
3799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3801 __func__, config->offload_info.version,
3802 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303803
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303804 /* Check if DSD audio format is supported in codec
3805 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303806 */
3807
3808 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303809 (!platform_check_codec_dsd_support(adev->platform) ||
3810 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303811 ret = -EINVAL;
3812 goto error_open;
3813 }
3814
Ashish Jain5106d362016-05-11 19:23:33 +05303815 /* Disable gapless if any of the following is true
3816 * passthrough playback
3817 * AV playback
3818 * Direct PCM playback
3819 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303820 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303821 (config->format == AUDIO_FORMAT_DSD) ||
3822 config->offload_info.has_video ||
3823 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303824 check_and_set_gapless_mode(adev, false);
3825 } else
3826 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003827
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303828 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003829 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3830 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303831 if (config->format == AUDIO_FORMAT_DSD) {
3832 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3833 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3834 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003835
3836 create_offload_callback_thread(out);
3837
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003838 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303839 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003840 if (ret != 0) {
3841 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3842 __func__, ret);
3843 goto error_open;
3844 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003845 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3846 if (config->sample_rate == 0)
3847 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3848 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3849 config->sample_rate != 8000) {
3850 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3851 ret = -EINVAL;
3852 goto error_open;
3853 }
3854 out->sample_rate = config->sample_rate;
3855 out->config.rate = config->sample_rate;
3856 if (config->format == AUDIO_FORMAT_DEFAULT)
3857 config->format = AUDIO_FORMAT_PCM_16_BIT;
3858 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3859 config->format = AUDIO_FORMAT_PCM_16_BIT;
3860 ret = -EINVAL;
3861 goto error_open;
3862 }
3863 out->format = config->format;
3864 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3865 out->config = pcm_config_afe_proxy_playback;
3866 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003867 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303868 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3869 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003870 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3871 out->flags);
3872 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303873 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3874 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3875 out->config = pcm_config_low_latency;
3876 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3877 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3878 out->config = pcm_config_deep_buffer;
3879 } else {
3880 /* primary path is the default path selected if no other outputs are available/suitable */
3881 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3882 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3883 }
3884 out->hal_ip_format = format = out->format;
3885 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3886 out->hal_op_format = pcm_format_to_hal(out->config.format);
3887 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3888 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003889 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303890 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3891 if (out->hal_ip_format != out->hal_op_format) {
3892 uint32_t buffer_size = out->config.period_size *
3893 format_to_bitwidth_table[out->hal_op_format] *
3894 out->config.channels;
3895 out->convert_buffer = calloc(1, buffer_size);
3896 if (out->convert_buffer == NULL){
3897 ALOGE("Allocation failed for convert buffer for size %d",
3898 out->compr_config.fragment_size);
3899 ret = -ENOMEM;
3900 goto error_open;
3901 }
3902 ALOGD("Convert buffer allocated of size %d", buffer_size);
3903 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 }
3905
Ashish Jain83a6cc22016-06-28 14:34:17 +05303906 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3907 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3908
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003909 /* TODO remove this hardcoding and check why width is zero*/
3910 if (out->bit_width == 0)
3911 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003912 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3913 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003914 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303915 out->bit_width, out->channel_mask,
3916 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003917 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3918 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3919 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003920 if(adev->primary_output == NULL)
3921 adev->primary_output = out;
3922 else {
3923 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003924 ret = -EEXIST;
3925 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003926 }
3927 }
3928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929 /* Check if this usecase is already existing */
3930 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003931 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3932 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003935 ret = -EEXIST;
3936 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 }
3938 pthread_mutex_unlock(&adev->lock);
3939
3940 out->stream.common.get_sample_rate = out_get_sample_rate;
3941 out->stream.common.set_sample_rate = out_set_sample_rate;
3942 out->stream.common.get_buffer_size = out_get_buffer_size;
3943 out->stream.common.get_channels = out_get_channels;
3944 out->stream.common.get_format = out_get_format;
3945 out->stream.common.set_format = out_set_format;
3946 out->stream.common.standby = out_standby;
3947 out->stream.common.dump = out_dump;
3948 out->stream.common.set_parameters = out_set_parameters;
3949 out->stream.common.get_parameters = out_get_parameters;
3950 out->stream.common.add_audio_effect = out_add_audio_effect;
3951 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3952 out->stream.get_latency = out_get_latency;
3953 out->stream.set_volume = out_set_volume;
3954 out->stream.write = out_write;
3955 out->stream.get_render_position = out_get_render_position;
3956 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003957 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003959 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003961 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003962 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963
3964 config->format = out->stream.common.get_format(&out->stream.common);
3965 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3966 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3967
3968 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303969 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003970 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003971
3972 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3973 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3974 popcount(out->channel_mask), out->playback_started);
3975
Eric Laurent994a6932013-07-17 11:51:42 -07003976 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003978
3979error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303980 if (out->convert_buffer)
3981 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003982 free(out);
3983 *stream_out = NULL;
3984 ALOGD("%s: exit: ret %d", __func__, ret);
3985 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986}
3987
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303988void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 struct audio_stream_out *stream)
3990{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003991 struct stream_out *out = (struct stream_out *)stream;
3992 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003993 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003994
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303995 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3996
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003997 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303998 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003999 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304000 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004001 if(ret != 0)
4002 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4003 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004004 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004005 out_standby(&stream->common);
4006
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004007 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004008 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004009 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004010 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004011 if (out->compr_config.codec != NULL)
4012 free(out->compr_config.codec);
4013 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004014
Ashish Jain83a6cc22016-06-28 14:34:17 +05304015 if (out->convert_buffer != NULL) {
4016 free(out->convert_buffer);
4017 out->convert_buffer = NULL;
4018 }
4019
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004020 if (adev->voice_tx_output == out)
4021 adev->voice_tx_output = NULL;
4022
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004023 pthread_cond_destroy(&out->cond);
4024 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004026 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027}
4028
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004029static void close_compress_sessions(struct audio_device *adev)
4030{
Mingming Yin7b762e72015-03-04 13:47:32 -08004031 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304032 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004033 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004034 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304035
4036 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004037 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304038 if (is_offload_usecase(usecase->id)) {
4039 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004040 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4041 out = usecase->stream.out;
4042 pthread_mutex_unlock(&adev->lock);
4043 out_standby(&out->stream.common);
4044 pthread_mutex_lock(&adev->lock);
4045 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304046 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004047 }
4048 pthread_mutex_unlock(&adev->lock);
4049}
4050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4052{
4053 struct audio_device *adev = (struct audio_device *)dev;
4054 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004056 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004057 int ret;
4058 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004060 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304063 if (!parms)
4064 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004065 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4066 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304067 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304068 if (strstr(snd_card_status, "OFFLINE")) {
4069 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304070 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004071 //close compress sessions on OFFLINE status
4072 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304073 } else if (strstr(snd_card_status, "ONLINE")) {
4074 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304075 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004076 //send dts hpx license if enabled
4077 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304078 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304079 }
4080
4081 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004082 status = voice_set_parameters(adev, parms);
4083 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004084 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004086 status = platform_set_parameters(adev->platform, parms);
4087 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004088 goto done;
4089
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004090 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4091 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004092 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4094 adev->bluetooth_nrec = true;
4095 else
4096 adev->bluetooth_nrec = false;
4097 }
4098
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004099 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4100 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4102 adev->screen_off = false;
4103 else
4104 adev->screen_off = true;
4105 }
4106
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004107 ret = str_parms_get_int(parms, "rotation", &val);
4108 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004109 bool reverse_speakers = false;
4110 switch(val) {
4111 // FIXME: note that the code below assumes that the speakers are in the correct placement
4112 // relative to the user when the device is rotated 90deg from its default rotation. This
4113 // assumption is device-specific, not platform-specific like this code.
4114 case 270:
4115 reverse_speakers = true;
4116 break;
4117 case 0:
4118 case 90:
4119 case 180:
4120 break;
4121 default:
4122 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004123 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004124 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004125 if (status == 0) {
4126 if (adev->speaker_lr_swap != reverse_speakers) {
4127 adev->speaker_lr_swap = reverse_speakers;
4128 // only update the selected device if there is active pcm playback
4129 struct audio_usecase *usecase;
4130 struct listnode *node;
4131 list_for_each(node, &adev->usecase_list) {
4132 usecase = node_to_item(node, struct audio_usecase, list);
4133 if (usecase->type == PCM_PLAYBACK) {
4134 select_devices(adev, usecase->id);
4135 break;
4136 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004137 }
4138 }
4139 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004140 }
4141
Mingming Yin514a8bc2014-07-29 15:22:21 -07004142 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4143 if (ret >= 0) {
4144 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4145 adev->bt_wb_speech_enabled = true;
4146 else
4147 adev->bt_wb_speech_enabled = false;
4148 }
4149
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004150 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4151 if (ret >= 0) {
4152 val = atoi(value);
4153 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004154 ALOGV("cache new ext disp type and edid");
4155 ret = platform_get_ext_disp_type(adev->platform);
4156 if (ret < 0) {
4157 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4158 return ret;
4159 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004160 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004161 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004162 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004163 /*
4164 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4165 * Per AudioPolicyManager, USB device is higher priority than WFD.
4166 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4167 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4168 * starting voice call on USB
4169 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004170 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4171 if (ret >= 0) {
4172 audio_extn_usb_add_device(val, atoi(value));
4173 }
vivek mehta344576a2016-04-12 18:56:03 -07004174 ALOGV("detected USB connect .. disable proxy");
4175 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004176 }
4177 }
4178
4179 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4180 if (ret >= 0) {
4181 val = atoi(value);
4182 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4183 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004184 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004185 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004186 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004187 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4188 if (ret >= 0) {
4189 audio_extn_usb_remove_device(val, atoi(value));
4190 }
vivek mehta344576a2016-04-12 18:56:03 -07004191 ALOGV("detected USB disconnect .. enable proxy");
4192 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004193 }
4194 }
4195
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304196 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4197 if (ret >= 0) {
4198 struct audio_usecase *usecase;
4199 struct listnode *node;
4200 list_for_each(node, &adev->usecase_list) {
4201 usecase = node_to_item(node, struct audio_usecase, list);
4202 if ((usecase->type == PCM_PLAYBACK) &&
4203 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4204 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304205 lock_output_stream(usecase->stream.out);
4206 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304207 //force device switch to re configure encoder
4208 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304209 audio_extn_a2dp_set_handoff_mode(false);
4210 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304211 break;
4212 }
4213 }
4214 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304215 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004216done:
4217 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004218 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304219error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004220 ALOGV("%s: exit with code(%d)", __func__, status);
4221 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222}
4223
4224static char* adev_get_parameters(const struct audio_hw_device *dev,
4225 const char *keys)
4226{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004227 struct audio_device *adev = (struct audio_device *)dev;
4228 struct str_parms *reply = str_parms_create();
4229 struct str_parms *query = str_parms_create_str(keys);
4230 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304231 char value[256] = {0};
4232 int ret = 0;
4233
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004234 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004235 if (reply) {
4236 str_parms_destroy(reply);
4237 }
4238 if (query) {
4239 str_parms_destroy(query);
4240 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004241 ALOGE("adev_get_parameters: failed to create query or reply");
4242 return NULL;
4243 }
4244
Naresh Tannirud7205b62014-06-20 02:54:48 +05304245 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4246 sizeof(value));
4247 if (ret >=0) {
4248 int val = 1;
4249 pthread_mutex_lock(&adev->snd_card_status.lock);
4250 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4251 val = 0;
4252 pthread_mutex_unlock(&adev->snd_card_status.lock);
4253 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4254 goto exit;
4255 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004256
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004257 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004258 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004259 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004260 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304261 pthread_mutex_unlock(&adev->lock);
4262
Naresh Tannirud7205b62014-06-20 02:54:48 +05304263exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004264 str = str_parms_to_str(reply);
4265 str_parms_destroy(query);
4266 str_parms_destroy(reply);
4267
4268 ALOGV("%s: exit: returns - %s", __func__, str);
4269 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270}
4271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004272static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273{
4274 return 0;
4275}
4276
4277static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4278{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004279 int ret;
4280 struct audio_device *adev = (struct audio_device *)dev;
4281 pthread_mutex_lock(&adev->lock);
4282 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004283 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004284 pthread_mutex_unlock(&adev->lock);
4285 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286}
4287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004288static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4289 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290{
4291 return -ENOSYS;
4292}
4293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004294static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4295 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296{
4297 return -ENOSYS;
4298}
4299
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004300static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4301 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302{
4303 return -ENOSYS;
4304}
4305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004306static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4307 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308{
4309 return -ENOSYS;
4310}
4311
4312static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4313{
4314 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 pthread_mutex_lock(&adev->lock);
4317 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004318 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004320 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004321 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004322 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004323 adev->current_call_output = NULL;
4324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 }
4326 pthread_mutex_unlock(&adev->lock);
4327 return 0;
4328}
4329
4330static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4331{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004332 int ret;
4333
4334 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004335 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004336 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4337 pthread_mutex_unlock(&adev->lock);
4338
4339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340}
4341
4342static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4343{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004344 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345 return 0;
4346}
4347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004348static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 const struct audio_config *config)
4350{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004351 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004353 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4354 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355}
4356
4357static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004358 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 audio_devices_t devices,
4360 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004361 struct audio_stream_in **stream_in,
4362 audio_input_flags_t flags __unused,
4363 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004364 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365{
4366 struct audio_device *adev = (struct audio_device *)dev;
4367 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004368 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004369 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004370 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304373 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4374 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377
4378 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004379
4380 if (!in) {
4381 ALOGE("failed to allocate input stream");
4382 return -ENOMEM;
4383 }
4384
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304385 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304386 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4387 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004388 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004389 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391 in->stream.common.get_sample_rate = in_get_sample_rate;
4392 in->stream.common.set_sample_rate = in_set_sample_rate;
4393 in->stream.common.get_buffer_size = in_get_buffer_size;
4394 in->stream.common.get_channels = in_get_channels;
4395 in->stream.common.get_format = in_get_format;
4396 in->stream.common.set_format = in_set_format;
4397 in->stream.common.standby = in_standby;
4398 in->stream.common.dump = in_dump;
4399 in->stream.common.set_parameters = in_set_parameters;
4400 in->stream.common.get_parameters = in_get_parameters;
4401 in->stream.common.add_audio_effect = in_add_audio_effect;
4402 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4403 in->stream.set_gain = in_set_gain;
4404 in->stream.read = in_read;
4405 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4406
4407 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004408 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410 in->standby = 1;
4411 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004412 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004413 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414
4415 /* Update config params with the requested sample rate and channels */
4416 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004417 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4418 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4419 is_low_latency = true;
4420#if LOW_LATENCY_CAPTURE_USE_CASE
4421 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4422#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004423 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004424 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004425
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004426 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004427 if (in->realtime) {
4428 in->config = pcm_config_audio_capture_rt;
4429 in->sample_rate = in->config.rate;
4430 in->af_period_multiplier = af_period_multiplier;
4431 } else {
4432 in->config = pcm_config_audio_capture;
4433 in->config.rate = config->sample_rate;
4434 in->sample_rate = config->sample_rate;
4435 in->af_period_multiplier = 1;
4436 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304437 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004439 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304440 if (adev->mode != AUDIO_MODE_IN_CALL) {
4441 ret = -EINVAL;
4442 goto err_open;
4443 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004444 if (config->sample_rate == 0)
4445 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4446 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4447 config->sample_rate != 8000) {
4448 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4449 ret = -EINVAL;
4450 goto err_open;
4451 }
4452 if (config->format == AUDIO_FORMAT_DEFAULT)
4453 config->format = AUDIO_FORMAT_PCM_16_BIT;
4454 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4455 config->format = AUDIO_FORMAT_PCM_16_BIT;
4456 ret = -EINVAL;
4457 goto err_open;
4458 }
4459
4460 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4461 in->config = pcm_config_afe_proxy_record;
4462 in->config.channels = channel_count;
4463 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304464 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304465 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4466 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004467 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004468 audio_extn_compr_cap_format_supported(config->format) &&
4469 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004470 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004471 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304472 /* restrict 24 bit capture for unprocessed source only
4473 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4474 */
4475 if (config->format == AUDIO_FORMAT_DEFAULT) {
4476 config->format = AUDIO_FORMAT_PCM_16_BIT;
4477 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4478 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4479 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4480 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4481 bool ret_error = false;
4482 in->bit_width = 24;
4483 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4484 from HAL is 24_packed and 8_24
4485 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4486 24_packed return error indicating supported format is 24_packed
4487 *> In case of any other source requesting 24 bit or float return error
4488 indicating format supported is 16 bit only.
4489
4490 on error flinger will retry with supported format passed
4491 */
4492 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4493 (source != AUDIO_SOURCE_CAMCORDER)) {
4494 config->format = AUDIO_FORMAT_PCM_16_BIT;
4495 if( config->sample_rate > 48000)
4496 config->sample_rate = 48000;
4497 ret_error = true;
4498 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4499 in->config.format = PCM_FORMAT_S24_3LE;
4500 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4501 in->config.format = PCM_FORMAT_S24_LE;
4502 } else {
4503 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4504 ret_error = true;
4505 }
4506
4507 if (ret_error) {
4508 ret = -EINVAL;
4509 goto err_open;
4510 }
4511 }
4512
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004513 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004514 if (!in->realtime) {
4515 in->format = config->format;
4516 frame_size = audio_stream_in_frame_size(&in->stream);
4517 buffer_size = get_input_buffer_size(config->sample_rate,
4518 config->format,
4519 channel_count,
4520 is_low_latency);
4521 in->config.period_size = buffer_size / frame_size;
4522 }
4523
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004524 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4525 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4526 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004527 (in->config.rate == 8000 || in->config.rate == 16000 ||
4528 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004529 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4530 voice_extn_compress_voip_open_input_stream(in);
4531 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004534 /* This stream could be for sound trigger lab,
4535 get sound trigger pcm if present */
4536 audio_extn_sound_trigger_check_and_get_session(in);
4537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004539 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004540 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541
4542err_open:
4543 free(in);
4544 *stream_in = NULL;
4545 return ret;
4546}
4547
4548static void adev_close_input_stream(struct audio_hw_device *dev,
4549 struct audio_stream_in *stream)
4550{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004551 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004552 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004553 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304554
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304555 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004556
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304557 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004558 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304559
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004560 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304561 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004562 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304563 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004564 if (ret != 0)
4565 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4566 __func__, ret);
4567 } else
4568 in_standby(&stream->common);
4569
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004570 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004571 audio_extn_ssr_deinit();
4572 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573
Mingming Yine62d7842013-10-25 16:26:03 -07004574 if(audio_extn_compr_cap_enabled() &&
4575 audio_extn_compr_cap_format_supported(in->config.format))
4576 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004577
Mingming Yinfd7607b2016-01-22 12:48:44 -08004578 if (in->is_st_session) {
4579 ALOGV("%s: sound trigger pcm stop lab", __func__);
4580 audio_extn_sound_trigger_stop_lab(in);
4581 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004582 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583 return;
4584}
4585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004586static int adev_dump(const audio_hw_device_t *device __unused,
4587 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588{
4589 return 0;
4590}
4591
4592static int adev_close(hw_device_t *device)
4593{
4594 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004595
4596 if (!adev)
4597 return 0;
4598
4599 pthread_mutex_lock(&adev_init_lock);
4600
4601 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004602 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004603 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304604 if (audio_extn_qaf_is_enabled())
4605 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004606 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004607 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004608 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004609 free(adev->snd_dev_ref_cnt);
4610 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004611 if (adev->adm_deinit)
4612 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004613 free(device);
4614 adev = NULL;
4615 }
4616 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 return 0;
4619}
4620
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004621/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4622 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4623 * just that it _might_ work.
4624 */
4625static int period_size_is_plausible_for_low_latency(int period_size)
4626{
4627 switch (period_size) {
4628 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004629 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004630 case 240:
4631 case 320:
4632 case 480:
4633 return 1;
4634 default:
4635 return 0;
4636 }
4637}
4638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639static int adev_open(const hw_module_t *module, const char *name,
4640 hw_device_t **device)
4641{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304642 int ret;
4643
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004644 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4646
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004647 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004648 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004649 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004650 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004651 ALOGD("%s: returning existing instance of adev", __func__);
4652 ALOGD("%s: exit", __func__);
4653 pthread_mutex_unlock(&adev_init_lock);
4654 return 0;
4655 }
4656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 adev = calloc(1, sizeof(struct audio_device));
4658
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004659 if (!adev) {
4660 pthread_mutex_unlock(&adev_init_lock);
4661 return -ENOMEM;
4662 }
4663
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004664 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4667 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4668 adev->device.common.module = (struct hw_module_t *)module;
4669 adev->device.common.close = adev_close;
4670
4671 adev->device.init_check = adev_init_check;
4672 adev->device.set_voice_volume = adev_set_voice_volume;
4673 adev->device.set_master_volume = adev_set_master_volume;
4674 adev->device.get_master_volume = adev_get_master_volume;
4675 adev->device.set_master_mute = adev_set_master_mute;
4676 adev->device.get_master_mute = adev_get_master_mute;
4677 adev->device.set_mode = adev_set_mode;
4678 adev->device.set_mic_mute = adev_set_mic_mute;
4679 adev->device.get_mic_mute = adev_get_mic_mute;
4680 adev->device.set_parameters = adev_set_parameters;
4681 adev->device.get_parameters = adev_get_parameters;
4682 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4683 adev->device.open_output_stream = adev_open_output_stream;
4684 adev->device.close_output_stream = adev_close_output_stream;
4685 adev->device.open_input_stream = adev_open_input_stream;
4686 adev->device.close_input_stream = adev_close_input_stream;
4687 adev->device.dump = adev_dump;
4688
4689 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004691 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004692 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004695 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004696 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004697 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004698 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004699 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004700 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004701 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004702 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304703 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304704 adev->perf_lock_opts[0] = 0x101;
4705 adev->perf_lock_opts[1] = 0x20E;
4706 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304707
4708 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4709 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004711 adev->platform = platform_init(adev);
4712 if (!adev->platform) {
4713 free(adev->snd_dev_ref_cnt);
4714 free(adev);
4715 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4716 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004717 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304718 pthread_mutex_destroy(&adev->lock);
4719 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004720 return -EINVAL;
4721 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004722
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304723 if (audio_extn_qaf_is_enabled()) {
4724 ret = audio_extn_qaf_init(adev);
4725 if (ret < 0) {
4726 free(adev);
4727 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4728 *device = NULL;
4729 pthread_mutex_unlock(&adev_init_lock);
4730 pthread_mutex_destroy(&adev->lock);
4731 return ret;
4732 }
4733
4734 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4735 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4736 }
4737
Naresh Tanniru4c630392014-05-12 01:05:52 +05304738 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4739
Eric Laurentc4aef752013-09-12 17:45:53 -07004740 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4741 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4742 if (adev->visualizer_lib == NULL) {
4743 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4744 } else {
4745 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4746 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004747 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004748 "visualizer_hal_start_output");
4749 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004750 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004751 "visualizer_hal_stop_output");
4752 }
4753 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004754 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004755 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004756 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004757
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004758 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4759 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4760 if (adev->offload_effects_lib == NULL) {
4761 ALOGE("%s: DLOPEN failed for %s", __func__,
4762 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4763 } else {
4764 ALOGV("%s: DLOPEN successful for %s", __func__,
4765 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4766 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304767 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004768 "offload_effects_bundle_hal_start_output");
4769 adev->offload_effects_stop_output =
4770 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4771 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004772 adev->offload_effects_set_hpx_state =
4773 (int (*)(bool))dlsym(adev->offload_effects_lib,
4774 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304775 adev->offload_effects_get_parameters =
4776 (void (*)(struct str_parms *, struct str_parms *))
4777 dlsym(adev->offload_effects_lib,
4778 "offload_effects_bundle_get_parameters");
4779 adev->offload_effects_set_parameters =
4780 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4781 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004782 }
4783 }
4784
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004785 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4786 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4787 if (adev->adm_lib == NULL) {
4788 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4789 } else {
4790 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4791 adev->adm_init = (adm_init_t)
4792 dlsym(adev->adm_lib, "adm_init");
4793 adev->adm_deinit = (adm_deinit_t)
4794 dlsym(adev->adm_lib, "adm_deinit");
4795 adev->adm_register_input_stream = (adm_register_input_stream_t)
4796 dlsym(adev->adm_lib, "adm_register_input_stream");
4797 adev->adm_register_output_stream = (adm_register_output_stream_t)
4798 dlsym(adev->adm_lib, "adm_register_output_stream");
4799 adev->adm_deregister_stream = (adm_deregister_stream_t)
4800 dlsym(adev->adm_lib, "adm_deregister_stream");
4801 adev->adm_request_focus = (adm_request_focus_t)
4802 dlsym(adev->adm_lib, "adm_request_focus");
4803 adev->adm_abandon_focus = (adm_abandon_focus_t)
4804 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004805 adev->adm_set_config = (adm_set_config_t)
4806 dlsym(adev->adm_lib, "adm_set_config");
4807 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4808 dlsym(adev->adm_lib, "adm_request_focus_v2");
4809 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4810 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4811 adev->adm_on_routing_change = (adm_on_routing_change_t)
4812 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004813 }
4814 }
4815
Mingming Yin514a8bc2014-07-29 15:22:21 -07004816 adev->bt_wb_speech_enabled = false;
4817
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004818 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 *device = &adev->device.common;
4820
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004821 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4822 &adev->streams_output_cfg_list);
4823
Kiran Kandi910e1862013-10-29 13:29:42 -07004824 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004825
4826 char value[PROPERTY_VALUE_MAX];
4827 int trial;
4828 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4829 trial = atoi(value);
4830 if (period_size_is_plausible_for_low_latency(trial)) {
4831 pcm_config_low_latency.period_size = trial;
4832 pcm_config_low_latency.start_threshold = trial / 4;
4833 pcm_config_low_latency.avail_min = trial / 4;
4834 configured_low_latency_capture_period_size = trial;
4835 }
4836 }
4837 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4838 trial = atoi(value);
4839 if (period_size_is_plausible_for_low_latency(trial)) {
4840 configured_low_latency_capture_period_size = trial;
4841 }
4842 }
4843
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004844 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4845 af_period_multiplier = atoi(value);
4846 if (af_period_multiplier < 0)
4847 af_period_multiplier = 2;
4848 else if (af_period_multiplier > 4)
4849 af_period_multiplier = 4;
4850
4851 ALOGV("new period_multiplier = %d", af_period_multiplier);
4852 }
4853
vivek mehta446c3962015-09-14 10:57:35 -07004854 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004855 pthread_mutex_unlock(&adev_init_lock);
4856
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004857 if (adev->adm_init)
4858 adev->adm_data = adev->adm_init();
4859
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304860 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004861 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862 return 0;
4863}
4864
4865static struct hw_module_methods_t hal_module_methods = {
4866 .open = adev_open,
4867};
4868
4869struct audio_module HAL_MODULE_INFO_SYM = {
4870 .common = {
4871 .tag = HARDWARE_MODULE_TAG,
4872 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4873 .hal_api_version = HARDWARE_HAL_API_VERSION,
4874 .id = AUDIO_HARDWARE_MODULE_ID,
4875 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004876 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 .methods = &hal_module_methods,
4878 },
4879};