blob: ee7647ea6bf7ba8bd6b5fbf9b8e83d42dd02b6d7 [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) ||
937 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530938 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
939 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
940 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530941 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
942 __func__, use_case_table[usecase->id],
943 platform_get_snd_device_name(usecase->out_snd_device));
944 disable_audio_route(adev, usecase);
945 switch_device[usecase->id] = true;
946 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 }
948 }
949
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530950 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
951 num_uc_to_switch);
952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700954 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530956 /* Make sure the previous devices to be disabled first and then enable the
957 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 list_for_each(node, &adev->usecase_list) {
959 usecase = node_to_item(node, struct audio_usecase, list);
960 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700961 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 }
963 }
964
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700965 list_for_each(node, &adev->usecase_list) {
966 usecase = node_to_item(node, struct audio_usecase, list);
967 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700968 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700969 }
970 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972 /* Re-route all the usecases on the shared backend other than the
973 specified usecase to new snd devices */
974 list_for_each(node, &adev->usecase_list) {
975 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530976 /* Update the out_snd_device only before enabling the audio route */
977 if (switch_device[usecase->id]) {
978 usecase->out_snd_device = snd_device;
979 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530980 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530981 use_case_table[usecase->id],
982 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530983 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530984 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 }
986 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 }
988}
989
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530990static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700991 struct audio_usecase *uc_info,
992 snd_device_t snd_device)
993{
994 struct listnode *node;
995 struct audio_usecase *usecase;
996 bool switch_device[AUDIO_USECASE_MAX];
997 int i, num_uc_to_switch = 0;
998
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530999 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1000 snd_device);
1001 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001002 /*
1003 * This function is to make sure that all the active capture usecases
1004 * are always routed to the same input sound device.
1005 * For example, if audio-record and voice-call usecases are currently
1006 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1007 * is received for voice call then we have to make sure that audio-record
1008 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1009 * because of the limitation that two devices cannot be enabled
1010 * at the same time if they share the same backend.
1011 */
1012 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1013 switch_device[i] = false;
1014
1015 list_for_each(node, &adev->usecase_list) {
1016 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001017 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001018 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301019 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001020 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301021 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001022 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001023 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001024 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1025 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001026 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001027 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001028 switch_device[usecase->id] = true;
1029 num_uc_to_switch++;
1030 }
1031 }
1032
1033 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001034 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001035
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301036 /* Make sure the previous devices to be disabled first and then enable the
1037 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001041 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001042 }
1043 }
1044
1045 list_for_each(node, &adev->usecase_list) {
1046 usecase = node_to_item(node, struct audio_usecase, list);
1047 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001048 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001049 }
1050 }
1051
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001052 /* Re-route all the usecases on the shared backend other than the
1053 specified usecase to new snd devices */
1054 list_for_each(node, &adev->usecase_list) {
1055 usecase = node_to_item(node, struct audio_usecase, list);
1056 /* Update the in_snd_device only before enabling the audio route */
1057 if (switch_device[usecase->id] ) {
1058 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001059 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301060 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001061 }
1062 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001063 }
1064}
1065
Mingming Yin3a941d42016-02-17 18:08:05 -08001066static void reset_hdmi_sink_caps(struct stream_out *out) {
1067 int i = 0;
1068
1069 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1070 out->supported_channel_masks[i] = 0;
1071 }
1072 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1073 out->supported_formats[i] = 0;
1074 }
1075 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1076 out->supported_sample_rates[i] = 0;
1077 }
1078}
1079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001081static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082{
Mingming Yin3a941d42016-02-17 18:08:05 -08001083 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001084 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085
Mingming Yin3a941d42016-02-17 18:08:05 -08001086 reset_hdmi_sink_caps(out);
1087
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001088 /* Cache ext disp type */
1089 ret = platform_get_ext_disp_type(adev->platform);
1090 if (ret < 0) {
1091 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1092 return ret;
1093 }
1094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001097 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001098 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1100 case 6:
1101 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1102 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1103 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1104 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1105 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 break;
1108 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001109 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001110 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 break;
1112 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001113
1114 // check channel format caps
1115 i = 0;
1116 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1117 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1118 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1119 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1120 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1121 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1122 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1123 }
1124
1125 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1126 ALOGV(":%s HDMI supports DTS format", __func__);
1127 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1128 }
1129
1130 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1131 ALOGV(":%s HDMI supports DTS HD format", __func__);
1132 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1133 }
1134
1135
1136 // check sample rate caps
1137 i = 0;
1138 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1139 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1140 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1141 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1142 }
1143 }
1144
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146}
1147
Alexy Josephb1379942016-01-29 15:49:38 -08001148audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001149 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001150{
1151 struct audio_usecase *usecase;
1152 struct listnode *node;
1153
1154 list_for_each(node, &adev->usecase_list) {
1155 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001156 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001157 ALOGV("%s: usecase id %d", __func__, usecase->id);
1158 return usecase->id;
1159 }
1160 }
1161 return USECASE_INVALID;
1162}
1163
Alexy Josephb1379942016-01-29 15:49:38 -08001164struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001165 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166{
1167 struct audio_usecase *usecase;
1168 struct listnode *node;
1169
1170 list_for_each(node, &adev->usecase_list) {
1171 usecase = node_to_item(node, struct audio_usecase, list);
1172 if (usecase->id == uc_id)
1173 return usecase;
1174 }
1175 return NULL;
1176}
1177
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301178/*
1179 * is a true native playback active
1180 */
1181bool audio_is_true_native_stream_active(struct audio_device *adev)
1182{
1183 bool active = false;
1184 int i = 0;
1185 struct listnode *node;
1186
1187 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1188 ALOGV("%s:napb: not in true mode or non hdphones device",
1189 __func__);
1190 active = false;
1191 goto exit;
1192 }
1193
1194 list_for_each(node, &adev->usecase_list) {
1195 struct audio_usecase *uc;
1196 uc = node_to_item(node, struct audio_usecase, list);
1197 struct stream_out *curr_out =
1198 (struct stream_out*) uc->stream.out;
1199
1200 if (curr_out && PCM_PLAYBACK == uc->type) {
1201 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1202 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1203 uc->id, curr_out->sample_rate,
1204 curr_out->bit_width,
1205 platform_get_snd_device_name(uc->out_snd_device));
1206
1207 if (is_offload_usecase(uc->id) &&
1208 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1209 active = true;
1210 ALOGD("%s:napb:native stream detected", __func__);
1211 }
1212 }
1213 }
1214exit:
1215 return active;
1216}
1217
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301218/*
1219 * if native DSD playback active
1220 */
1221bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1222{
1223 bool active = false;
1224 struct listnode *node = NULL;
1225 struct audio_usecase *uc = NULL;
1226 struct stream_out *curr_out = NULL;
1227
1228 list_for_each(node, &adev->usecase_list) {
1229 uc = node_to_item(node, struct audio_usecase, list);
1230 curr_out = (struct stream_out*) uc->stream.out;
1231
1232 if (curr_out && PCM_PLAYBACK == uc->type &&
1233 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1234 active = true;
1235 ALOGV("%s:DSD playback is active", __func__);
1236 }
1237 }
1238 return active;
1239}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301240
1241static bool force_device_switch(struct audio_usecase *usecase)
1242{
1243 bool ret = false;
1244 bool is_it_true_mode = false;
1245
1246 if (is_offload_usecase(usecase->id) &&
1247 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001248 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1249 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1250 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301251 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1252 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1253 (!is_it_true_mode && adev->native_playback_enabled)){
1254 ret = true;
1255 ALOGD("napb: time to toggle native mode");
1256 }
1257 }
1258
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301259 // Force all a2dp output devices to reconfigure for proper AFE encode format
1260 if((usecase->stream.out) &&
1261 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1262 audio_extn_a2dp_is_force_device_switch()) {
1263 ALOGD("Force a2dp device switch to update new encoder config");
1264 ret = true;
1265 }
1266
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301267 return ret;
1268}
1269
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001270int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001272 snd_device_t out_snd_device = SND_DEVICE_NONE;
1273 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 struct audio_usecase *usecase = NULL;
1275 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001276 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001277 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001278 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301281 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1282
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 usecase = get_usecase_from_list(adev, uc_id);
1284 if (usecase == NULL) {
1285 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1286 return -EINVAL;
1287 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001289 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001290 (usecase->type == VOIP_CALL) ||
1291 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001292 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001293 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001294 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 usecase->devices = usecase->stream.out->devices;
1296 } else {
1297 /*
1298 * If the voice call is active, use the sound devices of voice call usecase
1299 * so that it would not result any device switch. All the usecases will
1300 * be switched to new device when select_devices() is called for voice call
1301 * usecase. This is to avoid switching devices for voice call when
1302 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001303 * choose voice call device only if the use case device is
1304 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001305 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001306 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001307 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001308 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001309 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1310 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301311 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1312 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001313 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001314 in_snd_device = vc_usecase->in_snd_device;
1315 out_snd_device = vc_usecase->out_snd_device;
1316 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001317 } else if (voice_extn_compress_voip_is_active(adev)) {
1318 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001319 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001320 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1321 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001322 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001323 in_snd_device = voip_usecase->in_snd_device;
1324 out_snd_device = voip_usecase->out_snd_device;
1325 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001326 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001327 hfp_ucid = audio_extn_hfp_get_usecase();
1328 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001329 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001330 in_snd_device = hfp_usecase->in_snd_device;
1331 out_snd_device = hfp_usecase->out_snd_device;
1332 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001333 }
1334 if (usecase->type == PCM_PLAYBACK) {
1335 usecase->devices = usecase->stream.out->devices;
1336 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001337 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001338 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001339 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001340 if (usecase->stream.out == adev->primary_output &&
1341 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001342 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001343 select_devices(adev, adev->active_input->usecase);
1344 }
1345 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001346 } else if (usecase->type == PCM_CAPTURE) {
1347 usecase->devices = usecase->stream.in->device;
1348 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001350 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001351 if (adev->active_input &&
1352 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301353 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1354 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1355 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001356 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001357 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001358 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1359 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001360 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001361 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001362 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001363 }
1364 }
1365
1366 if (out_snd_device == usecase->out_snd_device &&
1367 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301368
1369 if (!force_device_switch(usecase))
1370 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371 }
1372
sangwoobc677242013-08-08 16:53:43 +09001373 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001374 out_snd_device, platform_get_snd_device_name(out_snd_device),
1375 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377 /*
1378 * Limitation: While in call, to do a device switch we need to disable
1379 * and enable both RX and TX devices though one of them is same as current
1380 * device.
1381 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001382 if ((usecase->type == VOICE_CALL) &&
1383 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1384 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001385 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001386 }
1387
1388 if (((usecase->type == VOICE_CALL) ||
1389 (usecase->type == VOIP_CALL)) &&
1390 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1391 /* Disable sidetone only if voice/voip call already exists */
1392 if (voice_is_call_state_active(adev) ||
1393 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001394 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001395 }
1396
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 /* Disable current sound devices */
1398 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001399 disable_audio_route(adev, usecase);
1400 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 }
1402
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001404 disable_audio_route(adev, usecase);
1405 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 }
1407
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001408 /* Applicable only on the targets that has external modem.
1409 * New device information should be sent to modem before enabling
1410 * the devices to reduce in-call device switch time.
1411 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001412 if ((usecase->type == VOICE_CALL) &&
1413 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1414 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001415 status = platform_switch_voice_call_enable_device_config(adev->platform,
1416 out_snd_device,
1417 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001418 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001419
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420 /* Enable new sound devices */
1421 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001422 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001423 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 }
1425
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001426 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301427 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001428 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001429 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001430
Avinash Vaish71a8b972014-07-24 15:36:33 +05301431 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001432 status = platform_switch_voice_call_device_post(adev->platform,
1433 out_snd_device,
1434 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301435 enable_audio_route_for_voice_usecases(adev, usecase);
1436 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001437
sangwoo170731f2013-06-08 15:36:36 +09001438 usecase->in_snd_device = in_snd_device;
1439 usecase->out_snd_device = out_snd_device;
1440
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301441 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001442 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301443 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001444 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301445 usecase->stream.out->flags,
1446 usecase->stream.out->format,
1447 usecase->stream.out->sample_rate,
1448 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301449 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301450 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001451 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301452 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001453
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001454 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001455
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001456 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1457 /* Enable sidetone only if other voice/voip call already exists */
1458 if (voice_is_call_state_active(adev) ||
1459 voice_extn_compress_voip_is_started(adev))
1460 voice_set_sidetone(adev, out_snd_device, true);
1461 }
1462
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001463 /* Applicable only on the targets that has external modem.
1464 * Enable device command should be sent to modem only after
1465 * enabling voice call mixer controls
1466 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001467 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001468 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1469 out_snd_device,
1470 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301471 ALOGD("%s: done",__func__);
1472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 return status;
1474}
1475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476static int stop_input_stream(struct stream_in *in)
1477{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301478 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479 struct audio_usecase *uc_info;
1480 struct audio_device *adev = in->dev;
1481
Eric Laurentc8400632013-02-14 19:04:54 -08001482 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483
Eric Laurent994a6932013-07-17 11:51:42 -07001484 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 uc_info = get_usecase_from_list(adev, in->usecase);
1487 if (uc_info == NULL) {
1488 ALOGE("%s: Could not find the usecase (%d) in the list",
1489 __func__, in->usecase);
1490 return -EINVAL;
1491 }
1492
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001493 /* Close in-call recording streams */
1494 voice_check_and_stop_incall_rec_usecase(adev, in);
1495
Eric Laurent150dbfe2013-02-27 14:31:02 -08001496 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001497 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498
1499 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001500 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001502 list_remove(&uc_info->list);
1503 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504
Eric Laurent994a6932013-07-17 11:51:42 -07001505 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 return ret;
1507}
1508
1509int start_input_stream(struct stream_in *in)
1510{
1511 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001512 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 struct audio_usecase *uc_info;
1514 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301515 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516
Mingming Yin2664a5b2015-09-03 10:53:11 -07001517 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1518 if (get_usecase_from_list(adev, usecase) == NULL)
1519 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301520 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1521 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001522
Naresh Tanniru80659832014-06-04 18:17:56 +05301523
1524 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301525 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301526 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301527 goto error_config;
1528 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301529
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001530 /* Check if source matches incall recording usecase criteria */
1531 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1532 if (ret)
1533 goto error_config;
1534 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001535 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1536
1537 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1538 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1539 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001540 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001541 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001542
Eric Laurentb23d5282013-05-14 15:27:20 -07001543 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 if (in->pcm_device_id < 0) {
1545 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1546 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001547 ret = -EINVAL;
1548 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001550
1551 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001553
1554 if (!uc_info) {
1555 ret = -ENOMEM;
1556 goto error_config;
1557 }
1558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 uc_info->id = in->usecase;
1560 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001561 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562 uc_info->devices = in->device;
1563 uc_info->in_snd_device = SND_DEVICE_NONE;
1564 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001566 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301567 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1568 adev->perf_lock_opts,
1569 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301572 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1573 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001574
1575 unsigned int flags = PCM_IN;
1576 unsigned int pcm_open_retry_count = 0;
1577
1578 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1579 flags |= PCM_MMAP | PCM_NOIRQ;
1580 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001581 } else if (in->realtime) {
1582 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001583 }
1584
1585 while (1) {
1586 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1587 flags, &in->config);
1588 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1589 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1590 if (in->pcm != NULL) {
1591 pcm_close(in->pcm);
1592 in->pcm = NULL;
1593 }
1594 if (pcm_open_retry_count-- == 0) {
1595 ret = -EIO;
1596 goto error_open;
1597 }
1598 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1599 continue;
1600 }
1601 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001603
1604 ALOGV("%s: pcm_prepare", __func__);
1605 ret = pcm_prepare(in->pcm);
1606 if (ret < 0) {
1607 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1608 pcm_close(in->pcm);
1609 in->pcm = NULL;
1610 goto error_open;
1611 }
1612
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001613 register_in_stream(in);
1614 if (in->realtime) {
1615 ret = pcm_start(in->pcm);
1616 if (ret < 0)
1617 goto error_open;
1618 }
1619
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301620 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001621 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001622
Eric Laurentc8400632013-02-14 19:04:54 -08001623 return ret;
1624
1625error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301626 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001628error_config:
1629 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301630 /*
1631 * sleep 50ms to allow sufficient time for kernel
1632 * drivers to recover incases like SSR.
1633 */
1634 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001636
1637 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638}
1639
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001640void lock_input_stream(struct stream_in *in)
1641{
1642 pthread_mutex_lock(&in->pre_lock);
1643 pthread_mutex_lock(&in->lock);
1644 pthread_mutex_unlock(&in->pre_lock);
1645}
1646
1647void lock_output_stream(struct stream_out *out)
1648{
1649 pthread_mutex_lock(&out->pre_lock);
1650 pthread_mutex_lock(&out->lock);
1651 pthread_mutex_unlock(&out->pre_lock);
1652}
1653
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001654/* must be called with out->lock locked */
1655static int send_offload_cmd_l(struct stream_out* out, int command)
1656{
1657 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1658
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001659 if (!cmd) {
1660 ALOGE("failed to allocate mem for command 0x%x", command);
1661 return -ENOMEM;
1662 }
1663
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001664 ALOGVV("%s %d", __func__, command);
1665
1666 cmd->cmd = command;
1667 list_add_tail(&out->offload_cmd_list, &cmd->node);
1668 pthread_cond_signal(&out->offload_cond);
1669 return 0;
1670}
1671
1672/* must be called iwth out->lock locked */
1673static void stop_compressed_output_l(struct stream_out *out)
1674{
1675 out->offload_state = OFFLOAD_STATE_IDLE;
1676 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001677 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678 if (out->compr != NULL) {
1679 compress_stop(out->compr);
1680 while (out->offload_thread_blocked) {
1681 pthread_cond_wait(&out->cond, &out->lock);
1682 }
1683 }
1684}
1685
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001686bool is_offload_usecase(audio_usecase_t uc_id)
1687{
1688 unsigned int i;
1689 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1690 if (uc_id == offload_usecases[i])
1691 return true;
1692 }
1693 return false;
1694}
1695
vivek mehta446c3962015-09-14 10:57:35 -07001696static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001697{
vivek mehta446c3962015-09-14 10:57:35 -07001698 audio_usecase_t ret_uc = USECASE_INVALID;
1699 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001700 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001701 if (!adev->multi_offload_enable) {
1702 if (is_direct_pcm)
1703 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1704 else
1705 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001706
vivek mehta446c3962015-09-14 10:57:35 -07001707 pthread_mutex_lock(&adev->lock);
1708 if (get_usecase_from_list(adev, ret_uc) != NULL)
1709 ret_uc = USECASE_INVALID;
1710 pthread_mutex_unlock(&adev->lock);
1711
1712 return ret_uc;
1713 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001714
1715 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001716 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1717 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1718 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1719 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001720 break;
1721 }
1722 }
vivek mehta446c3962015-09-14 10:57:35 -07001723
1724 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1725 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726}
1727
1728static void free_offload_usecase(struct audio_device *adev,
1729 audio_usecase_t uc_id)
1730{
vivek mehta446c3962015-09-14 10:57:35 -07001731 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001732 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001733
1734 if (!adev->multi_offload_enable)
1735 return;
1736
1737 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1738 if (offload_usecases[offload_uc_index] == uc_id) {
1739 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001740 break;
1741 }
1742 }
1743 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1744}
1745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746static void *offload_thread_loop(void *context)
1747{
1748 struct stream_out *out = (struct stream_out *) context;
1749 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001750 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1753 set_sched_policy(0, SP_FOREGROUND);
1754 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1755
1756 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001757 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 for (;;) {
1759 struct offload_cmd *cmd = NULL;
1760 stream_callback_event_t event;
1761 bool send_callback = false;
1762
1763 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1764 __func__, list_empty(&out->offload_cmd_list),
1765 out->offload_state);
1766 if (list_empty(&out->offload_cmd_list)) {
1767 ALOGV("%s SLEEPING", __func__);
1768 pthread_cond_wait(&out->offload_cond, &out->lock);
1769 ALOGV("%s RUNNING", __func__);
1770 continue;
1771 }
1772
1773 item = list_head(&out->offload_cmd_list);
1774 cmd = node_to_item(item, struct offload_cmd, node);
1775 list_remove(item);
1776
1777 ALOGVV("%s STATE %d CMD %d out->compr %p",
1778 __func__, out->offload_state, cmd->cmd, out->compr);
1779
1780 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1781 free(cmd);
1782 break;
1783 }
1784
1785 if (out->compr == NULL) {
1786 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001787 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 pthread_cond_signal(&out->cond);
1789 continue;
1790 }
1791 out->offload_thread_blocked = true;
1792 pthread_mutex_unlock(&out->lock);
1793 send_callback = false;
1794 switch(cmd->cmd) {
1795 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001796 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001797 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001798 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 send_callback = true;
1800 event = STREAM_CBK_EVENT_WRITE_READY;
1801 break;
1802 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001803 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301804 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001805 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301806 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001807 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301808 if (ret < 0)
1809 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301810 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301811 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001812 compress_drain(out->compr);
1813 else
1814 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301815 if (ret != -ENETRESET) {
1816 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301817 pthread_mutex_lock(&out->lock);
1818 out->send_new_metadata = 1;
1819 out->send_next_track_params = true;
1820 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301821 event = STREAM_CBK_EVENT_DRAIN_READY;
1822 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1823 } else
1824 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 break;
1826 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001827 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001829 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001830 send_callback = true;
1831 event = STREAM_CBK_EVENT_DRAIN_READY;
1832 break;
1833 default:
1834 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1835 break;
1836 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001837 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838 out->offload_thread_blocked = false;
1839 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001840 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001841 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001843 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001844 free(cmd);
1845 }
1846
1847 pthread_cond_signal(&out->cond);
1848 while (!list_empty(&out->offload_cmd_list)) {
1849 item = list_head(&out->offload_cmd_list);
1850 list_remove(item);
1851 free(node_to_item(item, struct offload_cmd, node));
1852 }
1853 pthread_mutex_unlock(&out->lock);
1854
1855 return NULL;
1856}
1857
1858static int create_offload_callback_thread(struct stream_out *out)
1859{
1860 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1861 list_init(&out->offload_cmd_list);
1862 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1863 offload_thread_loop, out);
1864 return 0;
1865}
1866
1867static int destroy_offload_callback_thread(struct stream_out *out)
1868{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001869 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 stop_compressed_output_l(out);
1871 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1872
1873 pthread_mutex_unlock(&out->lock);
1874 pthread_join(out->offload_thread, (void **) NULL);
1875 pthread_cond_destroy(&out->offload_cond);
1876
1877 return 0;
1878}
1879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880static int stop_output_stream(struct stream_out *out)
1881{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301882 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 struct audio_usecase *uc_info;
1884 struct audio_device *adev = out->dev;
1885
Eric Laurent994a6932013-07-17 11:51:42 -07001886 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 uc_info = get_usecase_from_list(adev, out->usecase);
1889 if (uc_info == NULL) {
1890 ALOGE("%s: Could not find the usecase (%d) in the list",
1891 __func__, out->usecase);
1892 return -EINVAL;
1893 }
1894
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001895 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301896 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001897 if (adev->visualizer_stop_output != NULL)
1898 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001899
1900 audio_extn_dts_remove_state_notifier_node(out->usecase);
1901
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001902 if (adev->offload_effects_stop_output != NULL)
1903 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1904 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001905
Eric Laurent150dbfe2013-02-27 14:31:02 -08001906 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001907 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001908
1909 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001910 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001912 list_remove(&uc_info->list);
1913 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914
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))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001917 ALOGV("Disable passthrough , reset mixer to pcm");
1918 /* NO_PASSTHROUGH */
1919 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001920 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001921 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1922 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001923
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301924 /* Must be called after removing the usecase from list */
1925 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301926 audio_extn_keep_alive_start();
1927
Eric Laurent994a6932013-07-17 11:51:42 -07001928 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 return ret;
1930}
1931
1932int start_output_stream(struct stream_out *out)
1933{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935 struct audio_usecase *uc_info;
1936 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301937 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001939 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1940 ret = -EINVAL;
1941 goto error_config;
1942 }
1943
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301944 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1945 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1946 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301947
Naresh Tanniru80659832014-06-04 18:17:56 +05301948 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301949 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301950 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301951 goto error_config;
1952 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301953
Eric Laurentb23d5282013-05-14 15:27:20 -07001954 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 if (out->pcm_device_id < 0) {
1956 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1957 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001958 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001959 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 }
1961
1962 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001963
1964 if (!uc_info) {
1965 ret = -ENOMEM;
1966 goto error_config;
1967 }
1968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 uc_info->id = out->usecase;
1970 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001971 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 uc_info->devices = out->devices;
1973 uc_info->in_snd_device = SND_DEVICE_NONE;
1974 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001975 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301977 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1978 adev->perf_lock_opts,
1979 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301980
1981 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1982 audio_extn_keep_alive_stop();
1983 if (audio_extn_passthru_is_enabled() &&
1984 audio_extn_passthru_is_passthrough_stream(out)) {
1985 audio_extn_passthru_on_start(out);
1986 audio_extn_passthru_update_stream_configuration(adev, out);
1987 }
1988 }
1989
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990 select_devices(adev, out->usecase);
1991
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001992 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1993 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001994 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001995 unsigned int flags = PCM_OUT;
1996 unsigned int pcm_open_retry_count = 0;
1997 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1998 flags |= PCM_MMAP | PCM_NOIRQ;
1999 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002000 } else if (out->realtime) {
2001 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002002 } else
2003 flags |= PCM_MONOTONIC;
2004
2005 while (1) {
2006 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2007 flags, &out->config);
2008 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2009 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2010 if (out->pcm != NULL) {
2011 pcm_close(out->pcm);
2012 out->pcm = NULL;
2013 }
2014 if (pcm_open_retry_count-- == 0) {
2015 ret = -EIO;
2016 goto error_open;
2017 }
2018 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2019 continue;
2020 }
2021 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002023
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002024 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2025 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002026
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002027 ALOGV("%s: pcm_prepare", __func__);
2028 if (pcm_is_ready(out->pcm)) {
2029 ret = pcm_prepare(out->pcm);
2030 if (ret < 0) {
2031 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2032 pcm_close(out->pcm);
2033 out->pcm = NULL;
2034 goto error_open;
2035 }
2036 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002038 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2039 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002041 out->compr = compress_open(adev->snd_card,
2042 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 COMPRESS_IN, &out->compr_config);
2044 if (out->compr && !is_compress_ready(out->compr)) {
2045 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2046 compress_close(out->compr);
2047 out->compr = NULL;
2048 ret = -EIO;
2049 goto error_open;
2050 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302051 /* compress_open sends params of the track, so reset the flag here */
2052 out->is_compr_metadata_avail = false;
2053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 if (out->offload_callback)
2055 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002056
Fred Oh3f43e742015-03-04 18:42:34 -08002057 /* Since small bufs uses blocking writes, a write will be blocked
2058 for the default max poll time (20s) in the event of an SSR.
2059 Reduce the poll time to observe and deal with SSR faster.
2060 */
Ashish Jain5106d362016-05-11 19:23:33 +05302061 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002062 compress_set_max_poll_wait(out->compr, 1000);
2063 }
2064
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002065 audio_extn_dts_create_state_notifier_node(out->usecase);
2066 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2067 popcount(out->channel_mask),
2068 out->playback_started);
2069
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002070#ifdef DS1_DOLBY_DDP_ENABLED
2071 if (audio_extn_is_dolby_format(out->format))
2072 audio_extn_dolby_send_ddp_endp_params(adev);
2073#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302074 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002075 if (adev->visualizer_start_output != NULL)
2076 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2077 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302078 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002079 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002082
2083 if (ret == 0) {
2084 register_out_stream(out);
2085 if (out->realtime) {
2086 ret = pcm_start(out->pcm);
2087 if (ret < 0)
2088 goto error_open;
2089 }
2090 }
2091
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302092 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002093 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002094
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002095 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302097 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002099error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302100 /*
2101 * sleep 50ms to allow sufficient time for kernel
2102 * drivers to recover incases like SSR.
2103 */
2104 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002105 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106}
2107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108static int check_input_parameters(uint32_t sample_rate,
2109 audio_format_t format,
2110 int channel_count)
2111{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002112 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302114 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2115 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2116 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002117 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302118 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002119
2120 switch (channel_count) {
2121 case 1:
2122 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302123 case 3:
2124 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002125 case 6:
2126 break;
2127 default:
2128 ret = -EINVAL;
2129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
2131 switch (sample_rate) {
2132 case 8000:
2133 case 11025:
2134 case 12000:
2135 case 16000:
2136 case 22050:
2137 case 24000:
2138 case 32000:
2139 case 44100:
2140 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302141 case 96000:
2142 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 break;
2144 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002145 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 }
2147
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002148 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149}
2150
2151static size_t get_input_buffer_size(uint32_t sample_rate,
2152 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002153 int channel_count,
2154 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155{
2156 size_t size = 0;
2157
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002158 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2159 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002161 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002162 if (is_low_latency)
2163 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302164
2165 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002167 /* make sure the size is multiple of 32 bytes
2168 * At 48 kHz mono 16-bit PCM:
2169 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2170 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2171 */
2172 size += 0x1f;
2173 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002174
2175 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176}
2177
Ashish Jain5106d362016-05-11 19:23:33 +05302178static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2179{
2180 uint64_t actual_frames_rendered = 0;
2181 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2182
2183 /* This adjustment accounts for buffering after app processor.
2184 * It is based on estimated DSP latency per use case, rather than exact.
2185 */
2186 int64_t platform_latency = platform_render_latency(out->usecase) *
2187 out->sample_rate / 1000000LL;
2188
2189 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2190 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2191 * hence only estimate.
2192 */
2193 int64_t signed_frames = out->written - kernel_buffer_size;
2194
2195 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2196
2197 if (signed_frames > 0)
2198 actual_frames_rendered = signed_frames;
2199
2200 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2201 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2202 (long long int)out->written, (int)kernel_buffer_size,
2203 audio_bytes_per_sample(out->compr_config.codec->format),
2204 popcount(out->channel_mask));
2205
2206 return actual_frames_rendered;
2207}
2208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2210{
2211 struct stream_out *out = (struct stream_out *)stream;
2212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214}
2215
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002216static int out_set_sample_rate(struct audio_stream *stream __unused,
2217 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218{
2219 return -ENOSYS;
2220}
2221
2222static size_t out_get_buffer_size(const struct audio_stream *stream)
2223{
2224 struct stream_out *out = (struct stream_out *)stream;
2225
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002226 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002227 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002228 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2229 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302230 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302231 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002233 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002234 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235}
2236
2237static uint32_t out_get_channels(const struct audio_stream *stream)
2238{
2239 struct stream_out *out = (struct stream_out *)stream;
2240
2241 return out->channel_mask;
2242}
2243
2244static audio_format_t out_get_format(const struct audio_stream *stream)
2245{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 struct stream_out *out = (struct stream_out *)stream;
2247
2248 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249}
2250
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002251static int out_set_format(struct audio_stream *stream __unused,
2252 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253{
2254 return -ENOSYS;
2255}
2256
2257static int out_standby(struct audio_stream *stream)
2258{
2259 struct stream_out *out = (struct stream_out *)stream;
2260 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002261
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302262 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2263 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002265 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002267 if (adev->adm_deregister_stream)
2268 adev->adm_deregister_stream(adev->adm_data, out->handle);
2269
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002270 if (is_offload_usecase(out->usecase))
2271 stop_compressed_output_l(out);
2272
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002273 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002275 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2276 voice_extn_compress_voip_close_output_stream(stream);
2277 pthread_mutex_unlock(&adev->lock);
2278 pthread_mutex_unlock(&out->lock);
2279 ALOGD("VOIP output entered standby");
2280 return 0;
2281 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 if (out->pcm) {
2283 pcm_close(out->pcm);
2284 out->pcm = NULL;
2285 }
2286 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002287 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302288 out->send_next_track_params = false;
2289 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002290 out->gapless_mdata.encoder_delay = 0;
2291 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 if (out->compr != NULL) {
2293 compress_close(out->compr);
2294 out->compr = NULL;
2295 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002298 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 }
2300 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302301 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 return 0;
2303}
2304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002305static int out_dump(const struct audio_stream *stream __unused,
2306 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307{
2308 return 0;
2309}
2310
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002311static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2312{
2313 int ret = 0;
2314 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002315
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002316 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002317 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002318 return -EINVAL;
2319 }
2320
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302321 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002322
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002323 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2324 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302325 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002327 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2328 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302329 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002330 }
2331
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002332 ALOGV("%s new encoder delay %u and padding %u", __func__,
2333 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2334
2335 return 0;
2336}
2337
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002338static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2339{
2340 return out == adev->primary_output || out == adev->voice_tx_output;
2341}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346 struct audio_device *adev = out->dev;
2347 struct str_parms *parms;
2348 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002349 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350
sangwoobc677242013-08-08 16:53:43 +09002351 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002352 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302354 if (!parms)
2355 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002356 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2357 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002359 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002360 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002362 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002363 * When HDMI cable is unplugged the music playback is paused and
2364 * the policy manager sends routing=0. But the audioflinger continues
2365 * to write data until standby time (3sec). As the HDMI core is
2366 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002367 * Avoid this by routing audio to speaker until standby.
2368 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002369 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2370 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302371 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002372 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2373 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002374 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302375 /*
2376 * When A2DP is disconnected the
2377 * music playback is paused and the policy manager sends routing=0
2378 * But the audioflingercontinues to write data until standby time
2379 * (3sec). As BT is turned off, the write gets blocked.
2380 * Avoid this by routing audio to speaker until standby.
2381 */
2382 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2383 (val == AUDIO_DEVICE_NONE)) {
2384 val = AUDIO_DEVICE_OUT_SPEAKER;
2385 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002386
2387 /*
2388 * select_devices() call below switches all the usecases on the same
2389 * backend to the new device. Refer to check_usecases_codec_backend() in
2390 * the select_devices(). But how do we undo this?
2391 *
2392 * For example, music playback is active on headset (deep-buffer usecase)
2393 * and if we go to ringtones and select a ringtone, low-latency usecase
2394 * will be started on headset+speaker. As we can't enable headset+speaker
2395 * and headset devices at the same time, select_devices() switches the music
2396 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2397 * So when the ringtone playback is completed, how do we undo the same?
2398 *
2399 * We are relying on the out_set_parameters() call on deep-buffer output,
2400 * once the ringtone playback is ended.
2401 * NOTE: We should not check if the current devices are same as new devices.
2402 * Because select_devices() must be called to switch back the music
2403 * playback to headset.
2404 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002405 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002406 audio_devices_t new_dev = val;
2407 bool same_dev = out->devices == new_dev;
2408 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002409
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002410 if (output_drives_call(adev, out)) {
2411 if(!voice_is_in_call(adev)) {
2412 if (adev->mode == AUDIO_MODE_IN_CALL) {
2413 adev->current_call_output = out;
2414 ret = voice_start_call(adev);
2415 }
2416 } else {
2417 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002418 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002419 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002420 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002421
2422 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002423 if (!same_dev) {
2424 ALOGV("update routing change");
2425 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302426 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2427 adev->perf_lock_opts,
2428 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002429 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002430 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302431 if (!same_dev)
2432 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002433 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002434 }
2435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002437 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002439
2440 if (out == adev->primary_output) {
2441 pthread_mutex_lock(&adev->lock);
2442 audio_extn_set_parameters(adev, parms);
2443 pthread_mutex_unlock(&adev->lock);
2444 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002445 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002446 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002447 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002448
2449 audio_extn_dts_create_state_notifier_node(out->usecase);
2450 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2451 popcount(out->channel_mask),
2452 out->playback_started);
2453
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002454 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002455 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302458error:
Eric Laurent994a6932013-07-17 11:51:42 -07002459 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return ret;
2461}
2462
2463static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002467 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 char value[256];
2469 struct str_parms *reply = str_parms_create();
2470 size_t i, j;
2471 int ret;
2472 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002473
2474 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002475 if (reply) {
2476 str_parms_destroy(reply);
2477 }
2478 if (query) {
2479 str_parms_destroy(query);
2480 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002481 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2482 return NULL;
2483 }
2484
Eric Laurent994a6932013-07-17 11:51:42 -07002485 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2487 if (ret >= 0) {
2488 value[0] = '\0';
2489 i = 0;
2490 while (out->supported_channel_masks[i] != 0) {
2491 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2492 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2493 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002494 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002496 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 first = false;
2498 break;
2499 }
2500 }
2501 i++;
2502 }
2503 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2504 str = str_parms_to_str(reply);
2505 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002506 voice_extn_out_get_parameters(out, query, reply);
2507 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002508 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002509 free(str);
2510 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002513
Alexy Joseph62142aa2015-11-16 15:10:34 -08002514
2515 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2516 if (ret >= 0) {
2517 value[0] = '\0';
2518 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2519 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302520 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002521 } else {
2522 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302523 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002524 }
2525 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002526 if (str)
2527 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002528 str = str_parms_to_str(reply);
2529 }
2530
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002531 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2532 if (ret >= 0) {
2533 value[0] = '\0';
2534 i = 0;
2535 first = true;
2536 while (out->supported_formats[i] != 0) {
2537 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2538 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2539 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002540 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002541 }
2542 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2543 first = false;
2544 break;
2545 }
2546 }
2547 i++;
2548 }
2549 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002550 if (str)
2551 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002552 str = str_parms_to_str(reply);
2553 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002554
2555 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2556 if (ret >= 0) {
2557 value[0] = '\0';
2558 i = 0;
2559 first = true;
2560 while (out->supported_sample_rates[i] != 0) {
2561 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2562 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2563 if (!first) {
2564 strlcat(value, "|", sizeof(value));
2565 }
2566 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2567 first = false;
2568 break;
2569 }
2570 }
2571 i++;
2572 }
2573 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2574 if (str)
2575 free(str);
2576 str = str_parms_to_str(reply);
2577 }
2578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 str_parms_destroy(query);
2580 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002581 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 return str;
2583}
2584
2585static uint32_t out_get_latency(const struct audio_stream_out *stream)
2586{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002587 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002589 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Alexy Josephaa54c872014-12-03 02:46:47 -08002591 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002592 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002593 } else if (out->realtime) {
2594 // since the buffer won't be filled up faster than realtime,
2595 // return a smaller number
2596 if (out->config.rate)
2597 period_ms = (out->af_period_multiplier * out->config.period_size *
2598 1000) / (out->config.rate);
2599 else
2600 period_ms = 0;
2601 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002602 } else {
2603 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002605 }
2606
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302607 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002608 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609}
2610
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302611static float AmpToDb(float amplification)
2612{
2613 if (amplification == 0) {
2614 return DSD_VOLUME_MIN_DB;
2615 }
2616 return 20 * log10(amplification);
2617}
2618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619static int out_set_volume(struct audio_stream_out *stream, float left,
2620 float right)
2621{
Eric Laurenta9024de2013-04-04 09:19:12 -07002622 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 int volume[2];
2624
Eric Laurenta9024de2013-04-04 09:19:12 -07002625 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2626 /* only take left channel into account: the API is for stereo anyway */
2627 out->muted = (left == 0.0f);
2628 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002629 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302630 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002631 /*
2632 * Set mute or umute on HDMI passthrough stream.
2633 * Only take left channel into account.
2634 * Mute is 0 and unmute 1
2635 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302636 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302637 } else if (out->format == AUDIO_FORMAT_DSD){
2638 char mixer_ctl_name[128] = "DSD Volume";
2639 struct audio_device *adev = out->dev;
2640 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2641
2642 if (!ctl) {
2643 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2644 __func__, mixer_ctl_name);
2645 return -EINVAL;
2646 }
2647 volume[0] = (int)(AmpToDb(left));
2648 volume[1] = (int)(AmpToDb(right));
2649 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2650 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002651 } else {
2652 char mixer_ctl_name[128];
2653 struct audio_device *adev = out->dev;
2654 struct mixer_ctl *ctl;
2655 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002656 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002658 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2659 "Compress Playback %d Volume", pcm_device_id);
2660 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2661 if (!ctl) {
2662 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2663 __func__, mixer_ctl_name);
2664 return -EINVAL;
2665 }
2666 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2667 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2668 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2669 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002670 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002671 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 return -ENOSYS;
2674}
2675
2676static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2677 size_t bytes)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302681 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002682 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002684 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302685
Naresh Tanniru80659832014-06-04 18:17:56 +05302686 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002687
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302688 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302689 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302690 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2691 pthread_mutex_unlock(&out->lock);
2692 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302693 } else {
2694 /* increase written size during SSR to avoid mismatch
2695 * with the written frames count in AF
2696 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002697 // bytes per frame
2698 size_t bpf = audio_bytes_per_sample(out->format) *
2699 audio_channel_count_from_out_mask(out->channel_mask);
2700 if (bpf != 0)
2701 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302702 ALOGD(" %s: sound card is not active/SSR state", __func__);
2703 ret= -EIO;
2704 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302705 }
2706 }
2707
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302708 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302709 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2710 if (audio_bytes_per_sample(out->format) != 0)
2711 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2712 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302713 goto exit;
2714 }
2715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002717 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002718 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002719 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2720 ret = voice_extn_compress_voip_start_output_stream(out);
2721 else
2722 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002723 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002724 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002726 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 goto exit;
2728 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002729
2730 if (last_known_cal_step != -1) {
2731 ALOGD("%s: retry previous failed cal level set", __func__);
2732 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735
Ashish Jain81eb2a82015-05-13 10:52:34 +05302736 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002737 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302738 adev->is_channel_status_set = true;
2739 }
2740
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002741 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002742 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002743 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002744 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002745 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2746 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302747 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2748 ALOGD("copl(%p):send next track params in gapless", out);
2749 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2750 out->send_next_track_params = false;
2751 out->is_compr_metadata_avail = false;
2752 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002753 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302754 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302755 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002756
Ashish Jain83a6cc22016-06-28 14:34:17 +05302757 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302758 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302759 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302760 pthread_mutex_unlock(&out->lock);
2761 return -EINVAL;
2762 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302763 audio_format_t dst_format = out->hal_op_format;
2764 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302765
2766 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2767 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2768
Ashish Jain83a6cc22016-06-28 14:34:17 +05302769 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302770 dst_format,
2771 buffer,
2772 src_format,
2773 frames);
2774
Ashish Jain83a6cc22016-06-28 14:34:17 +05302775 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302776 bytes_to_write);
2777
2778 /*Convert written bytes in audio flinger format*/
2779 if (ret > 0)
2780 ret = ((ret * format_to_bitwidth_table[out->format]) /
2781 format_to_bitwidth_table[dst_format]);
2782 }
2783 } else
2784 ret = compress_write(out->compr, buffer, bytes);
2785
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302786 if (ret < 0)
2787 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302788 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002789 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302790 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002791 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302792 } else if (-ENETRESET == ret) {
2793 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2794 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2795 pthread_mutex_unlock(&out->lock);
2796 out_standby(&out->stream.common);
2797 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 }
Ashish Jain5106d362016-05-11 19:23:33 +05302799 if ( ret == (ssize_t)bytes && !out->non_blocking)
2800 out->written += bytes;
2801
Naresh Tanniru80659832014-06-04 18:17:56 +05302802 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002804 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 out->playback_started = 1;
2806 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002807
2808 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2809 popcount(out->channel_mask),
2810 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002811 }
2812 pthread_mutex_unlock(&out->lock);
2813 return ret;
2814 } else {
2815 if (out->pcm) {
2816 if (out->muted)
2817 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002818
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302819 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002820
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002821 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002822
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002823 if (out->config.rate)
2824 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2825 out->config.rate;
2826
2827 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2828
2829 request_out_focus(out, ns);
2830
2831 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002832 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002833 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302834 out->convert_buffer != NULL) {
2835
2836 memcpy_by_audio_format(out->convert_buffer,
2837 out->hal_op_format,
2838 buffer,
2839 out->hal_ip_format,
2840 out->config.period_size * out->config.channels);
2841
2842 ret = pcm_write(out->pcm, out->convert_buffer,
2843 (out->config.period_size *
2844 out->config.channels *
2845 format_to_bitwidth_table[out->hal_op_format]));
2846 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002847 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302848 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002849
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002850 release_out_focus(out);
2851
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302852 if (ret < 0)
2853 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302854 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2855 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2856 else
2857 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 }
2860
2861exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302862 /* ToDo: There may be a corner case when SSR happens back to back during
2863 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302864 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302865 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302866 }
2867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 pthread_mutex_unlock(&out->lock);
2869
2870 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002871 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002872 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302873 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302874 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302875 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302876 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302877 out->standby = true;
2878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302880 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302881 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 }
2883 return bytes;
2884}
2885
2886static int out_get_render_position(const struct audio_stream_out *stream,
2887 uint32_t *dsp_frames)
2888{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302890 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002891
2892 if (dsp_frames == NULL)
2893 return -EINVAL;
2894
2895 *dsp_frames = 0;
2896 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002897 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302898
2899 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2900 * this operation and adev_close_output_stream(where out gets reset).
2901 */
2902 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2903 *dsp_frames = get_actual_pcm_frames_rendered(out);
2904 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2905 return 0;
2906 }
2907
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002908 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302909 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302910 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302912 if (ret < 0)
2913 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302915 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 }
2917 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302918 if (-ENETRESET == ret) {
2919 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2920 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2921 return -EINVAL;
2922 } else if(ret < 0) {
2923 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2924 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302925 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2926 /*
2927 * Handle corner case where compress session is closed during SSR
2928 * and timestamp is queried
2929 */
2930 ALOGE(" ERROR: sound card not active, return error");
2931 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302932 } else {
2933 return 0;
2934 }
Zhou Song32a556e2015-05-05 10:46:56 +08002935 } else if (audio_is_linear_pcm(out->format)) {
2936 *dsp_frames = out->written;
2937 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 } else
2939 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940}
2941
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002942static int out_add_audio_effect(const struct audio_stream *stream __unused,
2943 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944{
2945 return 0;
2946}
2947
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002948static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2949 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950{
2951 return 0;
2952}
2953
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002954static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2955 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956{
2957 return -EINVAL;
2958}
2959
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002960static int out_get_presentation_position(const struct audio_stream_out *stream,
2961 uint64_t *frames, struct timespec *timestamp)
2962{
2963 struct stream_out *out = (struct stream_out *)stream;
2964 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002965 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002966
Ashish Jain5106d362016-05-11 19:23:33 +05302967 /* below piece of code is not guarded against any lock because audioFliner serializes
2968 * this operation and adev_close_output_stream( where out gets reset).
2969 */
2970 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2971 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2972 *frames = get_actual_pcm_frames_rendered(out);
2973 /* this is the best we can do */
2974 clock_gettime(CLOCK_MONOTONIC, timestamp);
2975 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2976 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2977 return 0;
2978 }
2979
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002980 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002981
Ashish Jain5106d362016-05-11 19:23:33 +05302982 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2983 ret = compress_get_tstamp(out->compr, &dsp_frames,
2984 &out->sample_rate);
2985 ALOGVV("%s rendered frames %ld sample_rate %d",
2986 __func__, dsp_frames, out->sample_rate);
2987 *frames = dsp_frames;
2988 if (ret < 0)
2989 ret = -errno;
2990 if (-ENETRESET == ret) {
2991 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2992 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2993 ret = -EINVAL;
2994 } else
2995 ret = 0;
2996 /* this is the best we can do */
2997 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002998 } else {
2999 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003000 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003001 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3002 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003003 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003004 // This adjustment accounts for buffering after app processor.
3005 // It is based on estimated DSP latency per use case, rather than exact.
3006 signed_frames -=
3007 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3008
Eric Laurent949a0892013-09-20 09:20:13 -07003009 // It would be unusual for this value to be negative, but check just in case ...
3010 if (signed_frames >= 0) {
3011 *frames = signed_frames;
3012 ret = 0;
3013 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003014 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303015 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3016 *frames = out->written;
3017 clock_gettime(CLOCK_MONOTONIC, timestamp);
3018 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003019 }
3020 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003021 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003022 return ret;
3023}
3024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025static int out_set_callback(struct audio_stream_out *stream,
3026 stream_callback_t callback, void *cookie)
3027{
3028 struct stream_out *out = (struct stream_out *)stream;
3029
3030 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003031 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 out->offload_callback = callback;
3033 out->offload_cookie = cookie;
3034 pthread_mutex_unlock(&out->lock);
3035 return 0;
3036}
3037
3038static int out_pause(struct audio_stream_out* stream)
3039{
3040 struct stream_out *out = (struct stream_out *)stream;
3041 int status = -ENOSYS;
3042 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003043 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003044 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003045 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303047 struct audio_device *adev = out->dev;
3048 int snd_scard_state = get_snd_card_state(adev);
3049
3050 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3051 status = compress_pause(out->compr);
3052
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003054
Mingming Yin21854652016-04-13 11:54:02 -07003055 if (audio_extn_passthru_is_active()) {
3056 ALOGV("offload use case, pause passthru");
3057 audio_extn_passthru_on_pause(out);
3058 }
3059
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303060 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003061 audio_extn_dts_notify_playback_state(out->usecase, 0,
3062 out->sample_rate, popcount(out->channel_mask),
3063 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 }
3065 pthread_mutex_unlock(&out->lock);
3066 }
3067 return status;
3068}
3069
3070static int out_resume(struct audio_stream_out* stream)
3071{
3072 struct stream_out *out = (struct stream_out *)stream;
3073 int status = -ENOSYS;
3074 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003075 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003076 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003078 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303080 struct audio_device *adev = out->dev;
3081 int snd_scard_state = get_snd_card_state(adev);
3082
Mingming Yin21854652016-04-13 11:54:02 -07003083 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3084 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3085 pthread_mutex_lock(&out->dev->lock);
3086 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003087 pthread_mutex_unlock(&out->dev->lock);
3088 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303089 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003090 }
3091 if (!status) {
3092 out->offload_state = OFFLOAD_STATE_PLAYING;
3093 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303094 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003095 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3096 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 }
3098 pthread_mutex_unlock(&out->lock);
3099 }
3100 return status;
3101}
3102
3103static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3104{
3105 struct stream_out *out = (struct stream_out *)stream;
3106 int status = -ENOSYS;
3107 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003108 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003109 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3111 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3112 else
3113 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3114 pthread_mutex_unlock(&out->lock);
3115 }
3116 return status;
3117}
3118
3119static int out_flush(struct audio_stream_out* stream)
3120{
3121 struct stream_out *out = (struct stream_out *)stream;
3122 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003123 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003124 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003125 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003126 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303127 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003129 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 return 0;
3131 }
3132 return -ENOSYS;
3133}
3134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135/** audio_stream_in implementation **/
3136static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3137{
3138 struct stream_in *in = (struct stream_in *)stream;
3139
3140 return in->config.rate;
3141}
3142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003143static int in_set_sample_rate(struct audio_stream *stream __unused,
3144 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145{
3146 return -ENOSYS;
3147}
3148
3149static size_t in_get_buffer_size(const struct audio_stream *stream)
3150{
3151 struct stream_in *in = (struct stream_in *)stream;
3152
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003153 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3154 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003155 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3156 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003157
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003158 return in->config.period_size * in->af_period_multiplier *
3159 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160}
3161
3162static uint32_t in_get_channels(const struct audio_stream *stream)
3163{
3164 struct stream_in *in = (struct stream_in *)stream;
3165
3166 return in->channel_mask;
3167}
3168
3169static audio_format_t in_get_format(const struct audio_stream *stream)
3170{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003171 struct stream_in *in = (struct stream_in *)stream;
3172
3173 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174}
3175
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003176static int in_set_format(struct audio_stream *stream __unused,
3177 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178{
3179 return -ENOSYS;
3180}
3181
3182static int in_standby(struct audio_stream *stream)
3183{
3184 struct stream_in *in = (struct stream_in *)stream;
3185 struct audio_device *adev = in->dev;
3186 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303187 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3188 stream, in->usecase, use_case_table[in->usecase]);
3189
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003190 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003191 if (!in->standby && in->is_st_session) {
3192 ALOGD("%s: sound trigger pcm stop lab", __func__);
3193 audio_extn_sound_trigger_stop_lab(in);
3194 in->standby = 1;
3195 }
3196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003198 if (adev->adm_deregister_stream)
3199 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3200
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003201 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003203 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3204 voice_extn_compress_voip_close_input_stream(stream);
3205 ALOGD("VOIP input entered standby");
3206 } else {
3207 if (in->pcm) {
3208 pcm_close(in->pcm);
3209 in->pcm = NULL;
3210 }
3211 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003212 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003213 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 }
3215 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003216 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 return status;
3218}
3219
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003220static int in_dump(const struct audio_stream *stream __unused,
3221 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222{
3223 return 0;
3224}
3225
3226static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3227{
3228 struct stream_in *in = (struct stream_in *)stream;
3229 struct audio_device *adev = in->dev;
3230 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003232 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303234 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 parms = str_parms_create_str(kvpairs);
3236
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303237 if (!parms)
3238 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003239 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003240 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003241
3242 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3243 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 val = atoi(value);
3245 /* no audio source uses val == 0 */
3246 if ((in->source != val) && (val != 0)) {
3247 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003248 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3249 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3250 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003251 (in->config.rate == 8000 || in->config.rate == 16000 ||
3252 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003254 err = voice_extn_compress_voip_open_input_stream(in);
3255 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003256 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003257 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003258 }
3259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
3261 }
3262
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003263 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3264 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003266 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 in->device = val;
3268 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003269 if (!in->standby && !in->is_st_session) {
3270 ALOGV("update input routing change");
3271 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003272 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 }
3275 }
3276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003278 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279
3280 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303281error:
Eric Laurent994a6932013-07-17 11:51:42 -07003282 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 return ret;
3284}
3285
3286static char* in_get_parameters(const struct audio_stream *stream,
3287 const char *keys)
3288{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003289 struct stream_in *in = (struct stream_in *)stream;
3290 struct str_parms *query = str_parms_create_str(keys);
3291 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003292 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003293
3294 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003295 if (reply) {
3296 str_parms_destroy(reply);
3297 }
3298 if (query) {
3299 str_parms_destroy(query);
3300 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003301 ALOGE("in_get_parameters: failed to create query or reply");
3302 return NULL;
3303 }
3304
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003305 ALOGV("%s: enter: keys - %s", __func__, keys);
3306
3307 voice_extn_in_get_parameters(in, query, reply);
3308
3309 str = str_parms_to_str(reply);
3310 str_parms_destroy(query);
3311 str_parms_destroy(reply);
3312
3313 ALOGV("%s: exit: returns - %s", __func__, str);
3314 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315}
3316
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003317static int in_set_gain(struct audio_stream_in *stream __unused,
3318 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319{
3320 return 0;
3321}
3322
3323static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3324 size_t bytes)
3325{
3326 struct stream_in *in = (struct stream_in *)stream;
3327 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303328 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303329 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303330 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003332 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303333
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003334 if (in->is_st_session) {
3335 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3336 /* Read from sound trigger HAL */
3337 audio_extn_sound_trigger_read(in, buffer, bytes);
3338 pthread_mutex_unlock(&in->lock);
3339 return bytes;
3340 }
3341
Ashish Jainbbce4322016-02-16 13:25:27 +05303342 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003343 ALOGD(" %s: sound card is not active/SSR state", __func__);
3344 ret= -EIO;;
3345 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303346 }
3347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003349 pthread_mutex_lock(&adev->lock);
3350 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3351 ret = voice_extn_compress_voip_start_input_stream(in);
3352 else
3353 ret = start_input_stream(in);
3354 pthread_mutex_unlock(&adev->lock);
3355 if (ret != 0) {
3356 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
3358 in->standby = 0;
3359 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003361 // what's the duration requested by the client?
3362 long ns = 0;
3363
3364 if (in->config.rate)
3365 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3366 in->config.rate;
3367
3368 request_in_focus(in, ns);
3369 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303372 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003373 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303374 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003375 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003376 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003377 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303378 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003379 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303380 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3381 if (bytes % 4 == 0) {
3382 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3383 int_buf_stream = buffer;
3384 for (size_t itt=0; itt < bytes/4 ; itt++) {
3385 int_buf_stream[itt] >>= 8;
3386 }
3387 } else {
3388 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3389 ret = -EINVAL;
3390 goto exit;
3391 }
3392 } if (ret < 0) {
3393 ret = -errno;
3394 }
3395 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396 }
3397
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003398 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 /*
3401 * Instead of writing zeroes here, we could trust the hardware
3402 * to always provide zeroes when muted.
3403 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303404 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3405 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 memset(buffer, 0, bytes);
3407
3408exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303409 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303410 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003411 if (-ENETRESET == ret)
3412 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414 pthread_mutex_unlock(&in->lock);
3415
3416 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303417 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303418 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303419 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303420 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303421 in->standby = true;
3422 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303423 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003425 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303426 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303427 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 }
3429 return bytes;
3430}
3431
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003432static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433{
3434 return 0;
3435}
3436
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003437static int add_remove_audio_effect(const struct audio_stream *stream,
3438 effect_handle_t effect,
3439 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003441 struct stream_in *in = (struct stream_in *)stream;
3442 int status = 0;
3443 effect_descriptor_t desc;
3444
3445 status = (*effect)->get_descriptor(effect, &desc);
3446 if (status != 0)
3447 return status;
3448
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003449 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003450 pthread_mutex_lock(&in->dev->lock);
3451 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3452 in->enable_aec != enable &&
3453 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3454 in->enable_aec = enable;
3455 if (!in->standby)
3456 select_devices(in->dev, in->usecase);
3457 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003458 if (in->enable_ns != enable &&
3459 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3460 in->enable_ns = enable;
3461 if (!in->standby)
3462 select_devices(in->dev, in->usecase);
3463 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003464 pthread_mutex_unlock(&in->dev->lock);
3465 pthread_mutex_unlock(&in->lock);
3466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 return 0;
3468}
3469
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003470static int in_add_audio_effect(const struct audio_stream *stream,
3471 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472{
Eric Laurent994a6932013-07-17 11:51:42 -07003473 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003474 return add_remove_audio_effect(stream, effect, true);
3475}
3476
3477static int in_remove_audio_effect(const struct audio_stream *stream,
3478 effect_handle_t effect)
3479{
Eric Laurent994a6932013-07-17 11:51:42 -07003480 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003481 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482}
3483
3484static int adev_open_output_stream(struct audio_hw_device *dev,
3485 audio_io_handle_t handle,
3486 audio_devices_t devices,
3487 audio_output_flags_t flags,
3488 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003489 struct audio_stream_out **stream_out,
3490 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 struct audio_device *adev = (struct audio_device *)dev;
3493 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303494 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003495 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303498
3499 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3500 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003501 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303502 return -EINVAL;
3503 }
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3506
Mingming Yin3a941d42016-02-17 18:08:05 -08003507 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3508 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303509 devices, flags, &out->stream);
3510
3511
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003512 if (!out) {
3513 return -ENOMEM;
3514 }
3515
Haynes Mathew George204045b2015-02-25 20:32:03 -08003516 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003517 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003518 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 if (devices == AUDIO_DEVICE_NONE)
3521 devices = AUDIO_DEVICE_OUT_SPEAKER;
3522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 out->flags = flags;
3524 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003525 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003526 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003527 out->sample_rate = config->sample_rate;
3528 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3529 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003530 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003531 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003532 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303533 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Mingming Yin3a941d42016-02-17 18:08:05 -08003535 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3536 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3537 pthread_mutex_lock(&adev->lock);
3538 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3539 ret = read_hdmi_sink_caps(out);
3540 pthread_mutex_unlock(&adev->lock);
3541 if (ret != 0) {
3542 if (ret == -ENOSYS) {
3543 /* ignore and go with default */
3544 ret = 0;
3545 } else {
3546 ALOGE("error reading hdmi sink caps");
3547 goto error_open;
3548 }
3549 }
3550 }
3551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003553 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303554 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3555 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003556 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3557 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3558
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003559 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003560 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3561 /*
3562 * Do not handle stereo output in Multi-channel cases
3563 * Stereo case is handled in normal playback path
3564 */
3565 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3566 ret = AUDIO_CHANNEL_OUT_STEREO;
3567 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003568
3569 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3570 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003571 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003572 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003573 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003574
3575 if (config->sample_rate == 0)
3576 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3577 if (config->channel_mask == 0)
3578 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003579 if (config->format == 0)
3580 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003581
3582 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003584 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3586 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003588 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003590 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3591 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003592 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003593 ret = voice_extn_compress_voip_open_output_stream(out);
3594 if (ret != 0) {
3595 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3596 __func__, ret);
3597 goto error_open;
3598 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003599 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3600 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3601
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003602 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3603 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3604 ALOGE("%s: Unsupported Offload information", __func__);
3605 ret = -EINVAL;
3606 goto error_open;
3607 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003608
Mingming Yin3a941d42016-02-17 18:08:05 -08003609 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003610 if(config->offload_info.format == 0)
3611 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003612 if (config->offload_info.sample_rate == 0)
3613 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003614 }
3615
Mingming Yin90310102013-11-13 16:57:00 -08003616 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303617 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003618 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003619 ret = -EINVAL;
3620 goto error_open;
3621 }
3622
3623 out->compr_config.codec = (struct snd_codec *)
3624 calloc(1, sizeof(struct snd_codec));
3625
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003626 if (!out->compr_config.codec) {
3627 ret = -ENOMEM;
3628 goto error_open;
3629 }
3630
vivek mehta0ea887a2015-08-26 14:01:20 -07003631 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303632 out->stream.pause = out_pause;
3633 out->stream.flush = out_flush;
3634 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003635 out->usecase = get_offload_usecase(adev, true);
3636 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003637 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003638 out->stream.set_callback = out_set_callback;
3639 out->stream.pause = out_pause;
3640 out->stream.resume = out_resume;
3641 out->stream.drain = out_drain;
3642 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003643 out->usecase = get_offload_usecase(adev, false);
3644 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003645 }
vivek mehta446c3962015-09-14 10:57:35 -07003646
3647 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003648 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3649 config->format == 0 && config->sample_rate == 0 &&
3650 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003651 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003652 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3653 } else {
3654 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3655 ret = -EEXIST;
3656 goto error_open;
3657 }
vivek mehta446c3962015-09-14 10:57:35 -07003658 }
3659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 if (config->offload_info.channel_mask)
3661 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003662 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003664 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003665 } else {
3666 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3667 ret = -EINVAL;
3668 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003669 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003670
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003671 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 out->sample_rate = config->offload_info.sample_rate;
3673
Mingming Yin3ee55c62014-08-04 14:23:35 -07003674 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003675
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303676 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3677 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3678 audio_extn_dolby_send_ddp_endp_params(adev);
3679 audio_extn_dolby_set_dmid(adev);
3680 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003681
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003683 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684 out->compr_config.codec->bit_rate =
3685 config->offload_info.bit_rate;
3686 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303687 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303689 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003690 /*TODO: Do we need to change it for passthrough */
3691 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003692
Manish Dewangana6fc5442015-08-24 20:30:31 +05303693 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3694 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3695 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3696 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303697
3698 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3699 AUDIO_FORMAT_PCM) {
3700
3701 /*Based on platform support, configure appropriate alsa format for corresponding
3702 *hal input format.
3703 */
3704 out->compr_config.codec->format = hal_format_to_alsa(
3705 config->offload_info.format);
3706
Ashish Jain83a6cc22016-06-28 14:34:17 +05303707 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303708 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303709 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303710
3711 /*for direct PCM playback populate bit_width based on selected alsa format as
3712 *hal input format and alsa format might differ based on platform support.
3713 */
3714 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303715 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303716
3717 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3718
3719 /* Check if alsa session is configured with the same format as HAL input format,
3720 * if not then derive correct fragment size needed to accomodate the
3721 * conversion of HAL input format to alsa format.
3722 */
3723 audio_extn_utils_update_direct_pcm_fragment_size(out);
3724
3725 /*if hal input and output fragment size is different this indicates HAL input format is
3726 *not same as the alsa format
3727 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303728 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303729 /*Allocate a buffer to convert input data to the alsa configured format.
3730 *size of convert buffer is equal to the size required to hold one fragment size
3731 *worth of pcm data, this is because flinger does not write more than fragment_size
3732 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303733 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3734 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303735 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3736 ret = -ENOMEM;
3737 goto error_open;
3738 }
3739 }
3740 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3741 out->compr_config.fragment_size =
3742 audio_extn_passthru_get_buffer_size(&config->offload_info);
3743 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3744 } else {
3745 out->compr_config.fragment_size =
3746 platform_get_compress_offload_buffer_size(&config->offload_info);
3747 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3748 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003749
Amit Shekhar6f461b12014-08-01 14:52:58 -07003750 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303751 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003753 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3754 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003755
Alexy Josephaa54c872014-12-03 02:46:47 -08003756
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003757 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303758 out->send_next_track_params = false;
3759 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003760 out->offload_state = OFFLOAD_STATE_IDLE;
3761 out->playback_started = 0;
3762
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003763 audio_extn_dts_create_state_notifier_node(out->usecase);
3764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003765 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3766 __func__, config->offload_info.version,
3767 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303768
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303769 /*Check if DSD audio format is supported in codec
3770 *and there is no active native DSD use case
3771 */
3772
3773 if ((config->format == AUDIO_FORMAT_DSD) &&
3774 (!platform_check_codec_dsd_support(adev->platform) ||
3775 audio_is_dsd_native_stream_active(adev))) {
3776 ret = -EINVAL;
3777 goto error_open;
3778 }
3779
Ashish Jain5106d362016-05-11 19:23:33 +05303780 /* Disable gapless if any of the following is true
3781 * passthrough playback
3782 * AV playback
3783 * Direct PCM playback
3784 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303785 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303786 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303787 config->offload_info.has_video ||
3788 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3789 check_and_set_gapless_mode(adev, false);
3790 } else
3791 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003792
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303793 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003794 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3795 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303796 if (config->format == AUDIO_FORMAT_DSD) {
3797 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3798 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3799 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003800
3801 create_offload_callback_thread(out);
3802
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003803 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303804 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003805 if (ret != 0) {
3806 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3807 __func__, ret);
3808 goto error_open;
3809 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003810 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3811 if (config->sample_rate == 0)
3812 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3813 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3814 config->sample_rate != 8000) {
3815 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3816 ret = -EINVAL;
3817 goto error_open;
3818 }
3819 out->sample_rate = config->sample_rate;
3820 out->config.rate = config->sample_rate;
3821 if (config->format == AUDIO_FORMAT_DEFAULT)
3822 config->format = AUDIO_FORMAT_PCM_16_BIT;
3823 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3824 config->format = AUDIO_FORMAT_PCM_16_BIT;
3825 ret = -EINVAL;
3826 goto error_open;
3827 }
3828 out->format = config->format;
3829 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3830 out->config = pcm_config_afe_proxy_playback;
3831 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003832 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303833 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3834 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003835 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3836 out->flags);
3837 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303838 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3839 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3840 out->config = pcm_config_low_latency;
3841 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3842 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3843 out->config = pcm_config_deep_buffer;
3844 } else {
3845 /* primary path is the default path selected if no other outputs are available/suitable */
3846 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3847 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3848 }
3849 out->hal_ip_format = format = out->format;
3850 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3851 out->hal_op_format = pcm_format_to_hal(out->config.format);
3852 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3853 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003854 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303855 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3856 if (out->hal_ip_format != out->hal_op_format) {
3857 uint32_t buffer_size = out->config.period_size *
3858 format_to_bitwidth_table[out->hal_op_format] *
3859 out->config.channels;
3860 out->convert_buffer = calloc(1, buffer_size);
3861 if (out->convert_buffer == NULL){
3862 ALOGE("Allocation failed for convert buffer for size %d",
3863 out->compr_config.fragment_size);
3864 ret = -ENOMEM;
3865 goto error_open;
3866 }
3867 ALOGD("Convert buffer allocated of size %d", buffer_size);
3868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 }
3870
Ashish Jain83a6cc22016-06-28 14:34:17 +05303871 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3872 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3873
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003874 /* TODO remove this hardcoding and check why width is zero*/
3875 if (out->bit_width == 0)
3876 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003877 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3878 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003879 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303880 out->bit_width, out->channel_mask,
3881 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003882 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3883 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3884 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003885 if(adev->primary_output == NULL)
3886 adev->primary_output = out;
3887 else {
3888 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003889 ret = -EEXIST;
3890 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003891 }
3892 }
3893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 /* Check if this usecase is already existing */
3895 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003896 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3897 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003900 ret = -EEXIST;
3901 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 }
3903 pthread_mutex_unlock(&adev->lock);
3904
3905 out->stream.common.get_sample_rate = out_get_sample_rate;
3906 out->stream.common.set_sample_rate = out_set_sample_rate;
3907 out->stream.common.get_buffer_size = out_get_buffer_size;
3908 out->stream.common.get_channels = out_get_channels;
3909 out->stream.common.get_format = out_get_format;
3910 out->stream.common.set_format = out_set_format;
3911 out->stream.common.standby = out_standby;
3912 out->stream.common.dump = out_dump;
3913 out->stream.common.set_parameters = out_set_parameters;
3914 out->stream.common.get_parameters = out_get_parameters;
3915 out->stream.common.add_audio_effect = out_add_audio_effect;
3916 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3917 out->stream.get_latency = out_get_latency;
3918 out->stream.set_volume = out_set_volume;
3919 out->stream.write = out_write;
3920 out->stream.get_render_position = out_get_render_position;
3921 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003922 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003924 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003926 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003927 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928
3929 config->format = out->stream.common.get_format(&out->stream.common);
3930 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3931 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3932
3933 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303934 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003935 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003936
3937 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3938 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3939 popcount(out->channel_mask), out->playback_started);
3940
Eric Laurent994a6932013-07-17 11:51:42 -07003941 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003943
3944error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303945 if (out->convert_buffer)
3946 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003947 free(out);
3948 *stream_out = NULL;
3949 ALOGD("%s: exit: ret %d", __func__, ret);
3950 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951}
3952
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003953static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 struct audio_stream_out *stream)
3955{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003956 struct stream_out *out = (struct stream_out *)stream;
3957 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003958 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303960 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3961
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003962 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303963 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003964 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303965 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003966 if(ret != 0)
3967 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3968 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003969 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003970 out_standby(&stream->common);
3971
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003972 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003973 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003974 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003975 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 if (out->compr_config.codec != NULL)
3977 free(out->compr_config.codec);
3978 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003979
Ashish Jain83a6cc22016-06-28 14:34:17 +05303980 if (out->convert_buffer != NULL) {
3981 free(out->convert_buffer);
3982 out->convert_buffer = NULL;
3983 }
3984
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003985 if (adev->voice_tx_output == out)
3986 adev->voice_tx_output = NULL;
3987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988 pthread_cond_destroy(&out->cond);
3989 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003991 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992}
3993
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003994static void close_compress_sessions(struct audio_device *adev)
3995{
Mingming Yin7b762e72015-03-04 13:47:32 -08003996 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303997 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003998 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003999 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304000
4001 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004002 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304003 if (is_offload_usecase(usecase->id)) {
4004 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004005 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4006 out = usecase->stream.out;
4007 pthread_mutex_unlock(&adev->lock);
4008 out_standby(&out->stream.common);
4009 pthread_mutex_lock(&adev->lock);
4010 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304011 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004012 }
4013 pthread_mutex_unlock(&adev->lock);
4014}
4015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4017{
4018 struct audio_device *adev = (struct audio_device *)dev;
4019 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004021 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004022 int ret;
4023 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004025 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304028 if (!parms)
4029 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004030 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4031 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304032 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304033 if (strstr(snd_card_status, "OFFLINE")) {
4034 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304035 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004036 //close compress sessions on OFFLINE status
4037 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304038 } else if (strstr(snd_card_status, "ONLINE")) {
4039 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304040 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004041 //send dts hpx license if enabled
4042 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304043 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304044 }
4045
4046 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004047 status = voice_set_parameters(adev, parms);
4048 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004049 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004051 status = platform_set_parameters(adev->platform, parms);
4052 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004053 goto done;
4054
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004055 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4056 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004057 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4059 adev->bluetooth_nrec = true;
4060 else
4061 adev->bluetooth_nrec = false;
4062 }
4063
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004064 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4065 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4067 adev->screen_off = false;
4068 else
4069 adev->screen_off = true;
4070 }
4071
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004072 ret = str_parms_get_int(parms, "rotation", &val);
4073 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004074 bool reverse_speakers = false;
4075 switch(val) {
4076 // FIXME: note that the code below assumes that the speakers are in the correct placement
4077 // relative to the user when the device is rotated 90deg from its default rotation. This
4078 // assumption is device-specific, not platform-specific like this code.
4079 case 270:
4080 reverse_speakers = true;
4081 break;
4082 case 0:
4083 case 90:
4084 case 180:
4085 break;
4086 default:
4087 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004088 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004089 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004090 if (status == 0) {
4091 if (adev->speaker_lr_swap != reverse_speakers) {
4092 adev->speaker_lr_swap = reverse_speakers;
4093 // only update the selected device if there is active pcm playback
4094 struct audio_usecase *usecase;
4095 struct listnode *node;
4096 list_for_each(node, &adev->usecase_list) {
4097 usecase = node_to_item(node, struct audio_usecase, list);
4098 if (usecase->type == PCM_PLAYBACK) {
4099 select_devices(adev, usecase->id);
4100 break;
4101 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004102 }
4103 }
4104 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004105 }
4106
Mingming Yin514a8bc2014-07-29 15:22:21 -07004107 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4108 if (ret >= 0) {
4109 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4110 adev->bt_wb_speech_enabled = true;
4111 else
4112 adev->bt_wb_speech_enabled = false;
4113 }
4114
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004115 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4116 if (ret >= 0) {
4117 val = atoi(value);
4118 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004119 ALOGV("cache new ext disp type and edid");
4120 ret = platform_get_ext_disp_type(adev->platform);
4121 if (ret < 0) {
4122 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4123 return ret;
4124 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004125 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004126 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004127 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004128 /*
4129 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4130 * Per AudioPolicyManager, USB device is higher priority than WFD.
4131 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4132 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4133 * starting voice call on USB
4134 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004135 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4136 if (ret >= 0) {
4137 audio_extn_usb_add_device(val, atoi(value));
4138 }
vivek mehta344576a2016-04-12 18:56:03 -07004139 ALOGV("detected USB connect .. disable proxy");
4140 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004141 }
4142 }
4143
4144 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4145 if (ret >= 0) {
4146 val = atoi(value);
4147 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4148 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004149 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004150 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004151 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004152 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4153 if (ret >= 0) {
4154 audio_extn_usb_remove_device(val, atoi(value));
4155 }
vivek mehta344576a2016-04-12 18:56:03 -07004156 ALOGV("detected USB disconnect .. enable proxy");
4157 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004158 }
4159 }
4160
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304161 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4162 if (ret >= 0) {
4163 struct audio_usecase *usecase;
4164 struct listnode *node;
4165 list_for_each(node, &adev->usecase_list) {
4166 usecase = node_to_item(node, struct audio_usecase, list);
4167 if ((usecase->type == PCM_PLAYBACK) &&
4168 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4169 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304170 lock_output_stream(usecase->stream.out);
4171 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304172 //force device switch to re configure encoder
4173 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304174 audio_extn_a2dp_set_handoff_mode(false);
4175 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304176 break;
4177 }
4178 }
4179 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304180 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004181done:
4182 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004183 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304184error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004185 ALOGV("%s: exit with code(%d)", __func__, status);
4186 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187}
4188
4189static char* adev_get_parameters(const struct audio_hw_device *dev,
4190 const char *keys)
4191{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004192 struct audio_device *adev = (struct audio_device *)dev;
4193 struct str_parms *reply = str_parms_create();
4194 struct str_parms *query = str_parms_create_str(keys);
4195 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304196 char value[256] = {0};
4197 int ret = 0;
4198
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004199 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004200 if (reply) {
4201 str_parms_destroy(reply);
4202 }
4203 if (query) {
4204 str_parms_destroy(query);
4205 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004206 ALOGE("adev_get_parameters: failed to create query or reply");
4207 return NULL;
4208 }
4209
Naresh Tannirud7205b62014-06-20 02:54:48 +05304210 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4211 sizeof(value));
4212 if (ret >=0) {
4213 int val = 1;
4214 pthread_mutex_lock(&adev->snd_card_status.lock);
4215 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4216 val = 0;
4217 pthread_mutex_unlock(&adev->snd_card_status.lock);
4218 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4219 goto exit;
4220 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004221
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004222 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004223 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004224 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004225 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304226 pthread_mutex_unlock(&adev->lock);
4227
Naresh Tannirud7205b62014-06-20 02:54:48 +05304228exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004229 str = str_parms_to_str(reply);
4230 str_parms_destroy(query);
4231 str_parms_destroy(reply);
4232
4233 ALOGV("%s: exit: returns - %s", __func__, str);
4234 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235}
4236
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004237static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238{
4239 return 0;
4240}
4241
4242static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4243{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004244 int ret;
4245 struct audio_device *adev = (struct audio_device *)dev;
4246 pthread_mutex_lock(&adev->lock);
4247 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004248 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004249 pthread_mutex_unlock(&adev->lock);
4250 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251}
4252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004253static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4254 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255{
4256 return -ENOSYS;
4257}
4258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004259static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4260 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261{
4262 return -ENOSYS;
4263}
4264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004265static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4266 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267{
4268 return -ENOSYS;
4269}
4270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004271static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4272 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273{
4274 return -ENOSYS;
4275}
4276
4277static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4278{
4279 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 pthread_mutex_lock(&adev->lock);
4282 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004283 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004285 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004286 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004287 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004288 adev->current_call_output = NULL;
4289 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 }
4291 pthread_mutex_unlock(&adev->lock);
4292 return 0;
4293}
4294
4295static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4296{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004297 int ret;
4298
4299 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004300 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004301 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4302 pthread_mutex_unlock(&adev->lock);
4303
4304 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305}
4306
4307static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4308{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004309 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 return 0;
4311}
4312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004313static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 const struct audio_config *config)
4315{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004316 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004318 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4319 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320}
4321
4322static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004323 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324 audio_devices_t devices,
4325 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004326 struct audio_stream_in **stream_in,
4327 audio_input_flags_t flags __unused,
4328 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004329 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330{
4331 struct audio_device *adev = (struct audio_device *)dev;
4332 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004333 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004334 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004335 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304338 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4339 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304341 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342
4343 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004344
4345 if (!in) {
4346 ALOGE("failed to allocate input stream");
4347 return -ENOMEM;
4348 }
4349
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304350 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304351 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4352 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004353 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004354 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 in->stream.common.get_sample_rate = in_get_sample_rate;
4357 in->stream.common.set_sample_rate = in_set_sample_rate;
4358 in->stream.common.get_buffer_size = in_get_buffer_size;
4359 in->stream.common.get_channels = in_get_channels;
4360 in->stream.common.get_format = in_get_format;
4361 in->stream.common.set_format = in_set_format;
4362 in->stream.common.standby = in_standby;
4363 in->stream.common.dump = in_dump;
4364 in->stream.common.set_parameters = in_set_parameters;
4365 in->stream.common.get_parameters = in_get_parameters;
4366 in->stream.common.add_audio_effect = in_add_audio_effect;
4367 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4368 in->stream.set_gain = in_set_gain;
4369 in->stream.read = in_read;
4370 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4371
4372 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004373 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 in->standby = 1;
4376 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004377 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004378 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379
4380 /* Update config params with the requested sample rate and channels */
4381 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004382 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4383 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4384 is_low_latency = true;
4385#if LOW_LATENCY_CAPTURE_USE_CASE
4386 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4387#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004388 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004389 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004390
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004391 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004392 if (in->realtime) {
4393 in->config = pcm_config_audio_capture_rt;
4394 in->sample_rate = in->config.rate;
4395 in->af_period_multiplier = af_period_multiplier;
4396 } else {
4397 in->config = pcm_config_audio_capture;
4398 in->config.rate = config->sample_rate;
4399 in->sample_rate = config->sample_rate;
4400 in->af_period_multiplier = 1;
4401 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304402 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004404 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304405 if (adev->mode != AUDIO_MODE_IN_CALL) {
4406 ret = -EINVAL;
4407 goto err_open;
4408 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004409 if (config->sample_rate == 0)
4410 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4411 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4412 config->sample_rate != 8000) {
4413 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4414 ret = -EINVAL;
4415 goto err_open;
4416 }
4417 if (config->format == AUDIO_FORMAT_DEFAULT)
4418 config->format = AUDIO_FORMAT_PCM_16_BIT;
4419 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4420 config->format = AUDIO_FORMAT_PCM_16_BIT;
4421 ret = -EINVAL;
4422 goto err_open;
4423 }
4424
4425 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4426 in->config = pcm_config_afe_proxy_record;
4427 in->config.channels = channel_count;
4428 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304429 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304430 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4431 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004432 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004433 audio_extn_compr_cap_format_supported(config->format) &&
4434 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004435 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004436 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304437 /* restrict 24 bit capture for unprocessed source only
4438 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4439 */
4440 if (config->format == AUDIO_FORMAT_DEFAULT) {
4441 config->format = AUDIO_FORMAT_PCM_16_BIT;
4442 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4443 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4444 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4445 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4446 bool ret_error = false;
4447 in->bit_width = 24;
4448 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4449 from HAL is 24_packed and 8_24
4450 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4451 24_packed return error indicating supported format is 24_packed
4452 *> In case of any other source requesting 24 bit or float return error
4453 indicating format supported is 16 bit only.
4454
4455 on error flinger will retry with supported format passed
4456 */
4457 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4458 (source != AUDIO_SOURCE_CAMCORDER)) {
4459 config->format = AUDIO_FORMAT_PCM_16_BIT;
4460 if( config->sample_rate > 48000)
4461 config->sample_rate = 48000;
4462 ret_error = true;
4463 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4464 in->config.format = PCM_FORMAT_S24_3LE;
4465 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4466 in->config.format = PCM_FORMAT_S24_LE;
4467 } else {
4468 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4469 ret_error = true;
4470 }
4471
4472 if (ret_error) {
4473 ret = -EINVAL;
4474 goto err_open;
4475 }
4476 }
4477
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004478 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004479 if (!in->realtime) {
4480 in->format = config->format;
4481 frame_size = audio_stream_in_frame_size(&in->stream);
4482 buffer_size = get_input_buffer_size(config->sample_rate,
4483 config->format,
4484 channel_count,
4485 is_low_latency);
4486 in->config.period_size = buffer_size / frame_size;
4487 }
4488
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004489 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4490 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4491 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004492 (in->config.rate == 8000 || in->config.rate == 16000 ||
4493 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004494 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4495 voice_extn_compress_voip_open_input_stream(in);
4496 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004499 /* This stream could be for sound trigger lab,
4500 get sound trigger pcm if present */
4501 audio_extn_sound_trigger_check_and_get_session(in);
4502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004504 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004505 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506
4507err_open:
4508 free(in);
4509 *stream_in = NULL;
4510 return ret;
4511}
4512
4513static void adev_close_input_stream(struct audio_hw_device *dev,
4514 struct audio_stream_in *stream)
4515{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004516 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004517 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004518 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304519
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304520 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004521
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304522 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004523 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304524
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004525 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304526 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004527 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304528 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004529 if (ret != 0)
4530 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4531 __func__, ret);
4532 } else
4533 in_standby(&stream->common);
4534
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004535 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004536 audio_extn_ssr_deinit();
4537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538
Mingming Yine62d7842013-10-25 16:26:03 -07004539 if(audio_extn_compr_cap_enabled() &&
4540 audio_extn_compr_cap_format_supported(in->config.format))
4541 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004542
Mingming Yinfd7607b2016-01-22 12:48:44 -08004543 if (in->is_st_session) {
4544 ALOGV("%s: sound trigger pcm stop lab", __func__);
4545 audio_extn_sound_trigger_stop_lab(in);
4546 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004547 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 return;
4549}
4550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004551static int adev_dump(const audio_hw_device_t *device __unused,
4552 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553{
4554 return 0;
4555}
4556
4557static int adev_close(hw_device_t *device)
4558{
4559 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004560
4561 if (!adev)
4562 return 0;
4563
4564 pthread_mutex_lock(&adev_init_lock);
4565
4566 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004567 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004568 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004569 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004570 audio_route_free(adev->audio_route);
4571 free(adev->snd_dev_ref_cnt);
4572 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004573 if (adev->adm_deinit)
4574 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004575 free(device);
4576 adev = NULL;
4577 }
4578 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 return 0;
4581}
4582
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004583/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4584 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4585 * just that it _might_ work.
4586 */
4587static int period_size_is_plausible_for_low_latency(int period_size)
4588{
4589 switch (period_size) {
4590 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004591 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004592 case 240:
4593 case 320:
4594 case 480:
4595 return 1;
4596 default:
4597 return 0;
4598 }
4599}
4600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601static int adev_open(const hw_module_t *module, const char *name,
4602 hw_device_t **device)
4603{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004604 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4606
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004607 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004608 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004609 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004610 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004611 ALOGD("%s: returning existing instance of adev", __func__);
4612 ALOGD("%s: exit", __func__);
4613 pthread_mutex_unlock(&adev_init_lock);
4614 return 0;
4615 }
4616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 adev = calloc(1, sizeof(struct audio_device));
4618
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004619 if (!adev) {
4620 pthread_mutex_unlock(&adev_init_lock);
4621 return -ENOMEM;
4622 }
4623
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004624 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4627 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4628 adev->device.common.module = (struct hw_module_t *)module;
4629 adev->device.common.close = adev_close;
4630
4631 adev->device.init_check = adev_init_check;
4632 adev->device.set_voice_volume = adev_set_voice_volume;
4633 adev->device.set_master_volume = adev_set_master_volume;
4634 adev->device.get_master_volume = adev_get_master_volume;
4635 adev->device.set_master_mute = adev_set_master_mute;
4636 adev->device.get_master_mute = adev_get_master_mute;
4637 adev->device.set_mode = adev_set_mode;
4638 adev->device.set_mic_mute = adev_set_mic_mute;
4639 adev->device.get_mic_mute = adev_get_mic_mute;
4640 adev->device.set_parameters = adev_set_parameters;
4641 adev->device.get_parameters = adev_get_parameters;
4642 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4643 adev->device.open_output_stream = adev_open_output_stream;
4644 adev->device.close_output_stream = adev_close_output_stream;
4645 adev->device.open_input_stream = adev_open_input_stream;
4646 adev->device.close_input_stream = adev_close_input_stream;
4647 adev->device.dump = adev_dump;
4648
4649 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004651 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004652 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004655 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004656 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004657 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004658 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004659 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004660 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004661 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004662 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304663 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304664 adev->perf_lock_opts[0] = 0x101;
4665 adev->perf_lock_opts[1] = 0x20E;
4666 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304667
4668 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4669 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004671 adev->platform = platform_init(adev);
4672 if (!adev->platform) {
4673 free(adev->snd_dev_ref_cnt);
4674 free(adev);
4675 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4676 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004677 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004678 return -EINVAL;
4679 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004680
Naresh Tanniru4c630392014-05-12 01:05:52 +05304681 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4682
Eric Laurentc4aef752013-09-12 17:45:53 -07004683 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4684 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4685 if (adev->visualizer_lib == NULL) {
4686 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4687 } else {
4688 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4689 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004690 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004691 "visualizer_hal_start_output");
4692 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004693 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004694 "visualizer_hal_stop_output");
4695 }
4696 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004697 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004698 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004699
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004700 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4701 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4702 if (adev->offload_effects_lib == NULL) {
4703 ALOGE("%s: DLOPEN failed for %s", __func__,
4704 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4705 } else {
4706 ALOGV("%s: DLOPEN successful for %s", __func__,
4707 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4708 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304709 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004710 "offload_effects_bundle_hal_start_output");
4711 adev->offload_effects_stop_output =
4712 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4713 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004714 adev->offload_effects_set_hpx_state =
4715 (int (*)(bool))dlsym(adev->offload_effects_lib,
4716 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304717 adev->offload_effects_get_parameters =
4718 (void (*)(struct str_parms *, struct str_parms *))
4719 dlsym(adev->offload_effects_lib,
4720 "offload_effects_bundle_get_parameters");
4721 adev->offload_effects_set_parameters =
4722 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4723 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004724 }
4725 }
4726
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004727 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4728 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4729 if (adev->adm_lib == NULL) {
4730 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4731 } else {
4732 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4733 adev->adm_init = (adm_init_t)
4734 dlsym(adev->adm_lib, "adm_init");
4735 adev->adm_deinit = (adm_deinit_t)
4736 dlsym(adev->adm_lib, "adm_deinit");
4737 adev->adm_register_input_stream = (adm_register_input_stream_t)
4738 dlsym(adev->adm_lib, "adm_register_input_stream");
4739 adev->adm_register_output_stream = (adm_register_output_stream_t)
4740 dlsym(adev->adm_lib, "adm_register_output_stream");
4741 adev->adm_deregister_stream = (adm_deregister_stream_t)
4742 dlsym(adev->adm_lib, "adm_deregister_stream");
4743 adev->adm_request_focus = (adm_request_focus_t)
4744 dlsym(adev->adm_lib, "adm_request_focus");
4745 adev->adm_abandon_focus = (adm_abandon_focus_t)
4746 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004747 adev->adm_set_config = (adm_set_config_t)
4748 dlsym(adev->adm_lib, "adm_set_config");
4749 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4750 dlsym(adev->adm_lib, "adm_request_focus_v2");
4751 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4752 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4753 adev->adm_on_routing_change = (adm_on_routing_change_t)
4754 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004755 }
4756 }
4757
Mingming Yin514a8bc2014-07-29 15:22:21 -07004758 adev->bt_wb_speech_enabled = false;
4759
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004760 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 *device = &adev->device.common;
4762
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004763 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4764 &adev->streams_output_cfg_list);
4765
Kiran Kandi910e1862013-10-29 13:29:42 -07004766 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004767
4768 char value[PROPERTY_VALUE_MAX];
4769 int trial;
4770 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4771 trial = atoi(value);
4772 if (period_size_is_plausible_for_low_latency(trial)) {
4773 pcm_config_low_latency.period_size = trial;
4774 pcm_config_low_latency.start_threshold = trial / 4;
4775 pcm_config_low_latency.avail_min = trial / 4;
4776 configured_low_latency_capture_period_size = trial;
4777 }
4778 }
4779 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4780 trial = atoi(value);
4781 if (period_size_is_plausible_for_low_latency(trial)) {
4782 configured_low_latency_capture_period_size = trial;
4783 }
4784 }
4785
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004786 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4787 af_period_multiplier = atoi(value);
4788 if (af_period_multiplier < 0)
4789 af_period_multiplier = 2;
4790 else if (af_period_multiplier > 4)
4791 af_period_multiplier = 4;
4792
4793 ALOGV("new period_multiplier = %d", af_period_multiplier);
4794 }
4795
vivek mehta446c3962015-09-14 10:57:35 -07004796 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004797 pthread_mutex_unlock(&adev_init_lock);
4798
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004799 if (adev->adm_init)
4800 adev->adm_data = adev->adm_init();
4801
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304802 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004803 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804 return 0;
4805}
4806
4807static struct hw_module_methods_t hal_module_methods = {
4808 .open = adev_open,
4809};
4810
4811struct audio_module HAL_MODULE_INFO_SYM = {
4812 .common = {
4813 .tag = HARDWARE_MODULE_TAG,
4814 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4815 .hal_api_version = HARDWARE_HAL_API_VERSION,
4816 .id = AUDIO_HARDWARE_MODULE_ID,
4817 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004818 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 .methods = &hal_module_methods,
4820 },
4821};