blob: 3077f89b212d59fd244b39097850da3964e35a93 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625/*
626 * Enable ASRC mode if native or DSD stream is active.
627 */
628static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
629{
630 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635
636 list_for_each(node, &adev->usecase_list) {
637 uc = node_to_item(node, struct audio_usecase, list);
638 curr_out = (struct stream_out*) uc->stream.out;
639
640 if (curr_out && PCM_PLAYBACK == uc->type) {
641 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
642 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
643 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
644 __func__);
645 audio_route_apply_and_update_path(adev->audio_route,
646 "asrc-mode");
647 adev->asrc_mode_enabled = true;
648 break;
649 }
650 }
651 }
652 }
653}
654
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700655int pcm_ioctl(struct pcm *pcm, int request, ...)
656{
657 va_list ap;
658 void * arg;
659 int pcm_fd = *(int*)pcm;
660
661 va_start(ap, request);
662 arg = va_arg(ap, void *);
663 va_end(ap);
664
665 return ioctl(pcm_fd, request, arg);
666}
667
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700668int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700672 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800673
674 if (usecase == NULL)
675 return -EINVAL;
676
677 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
678
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800684#ifdef DS1_DOLBY_DAP_ENABLED
685 audio_extn_dolby_set_dmid(adev);
686 audio_extn_dolby_set_endpoint(adev);
687#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700688 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700689 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530690 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700691 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530692 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800693 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700694 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700695 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700696 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 ALOGV("%s: exit", __func__);
698 return 0;
699}
700
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700701int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530707 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 if (usecase->type == PCM_CAPTURE)
712 snd_device = usecase->in_snd_device;
713 else
714 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800715 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700716 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700717 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700719 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530720 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 ALOGV("%s: exit", __func__);
722 return 0;
723}
724
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700725int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530728 int i, num_devices = 0;
729 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700730 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
731
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800732 if (snd_device < SND_DEVICE_MIN ||
733 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800734 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800735 return -EINVAL;
736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737
738 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700739
740 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
741 ALOGE("%s: Invalid sound device returned", __func__);
742 return -EINVAL;
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700745 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700746 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 return 0;
748 }
749
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530750
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700751 if (audio_extn_spkr_prot_is_enabled())
752 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800754 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
755 audio_extn_spkr_prot_is_enabled()) {
756 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700757 adev->snd_dev_ref_cnt[snd_device]--;
758 return -EINVAL;
759 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200760 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800761 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800762 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200763 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 return -EINVAL;
765 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530766 } else if (platform_can_split_snd_device(adev->platform, snd_device,
767 &num_devices, new_snd_devices)) {
768 for (i = 0; i < num_devices; i++) {
769 enable_snd_device(adev, new_snd_devices[i]);
770 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530773
774 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
775 (audio_extn_a2dp_start_playback() < 0)) {
776 ALOGE(" fail to configure A2dp control path ");
777 return -EINVAL;
778 }
779
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700780 /* due to the possibility of calibration overwrite between listen
781 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700782 audio_extn_sound_trigger_update_device_status(snd_device,
783 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530784 audio_extn_listen_update_device_status(snd_device,
785 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700786 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 audio_extn_sound_trigger_update_device_status(snd_device,
789 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530790 audio_extn_listen_update_device_status(snd_device,
791 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700792 return -EINVAL;
793 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300794 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
797 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
798 !adev->native_playback_enabled &&
799 audio_is_true_native_stream_active(adev)) {
800 ALOGD("%s: %d: napb: enabling native mode in hardware",
801 __func__, __LINE__);
802 audio_route_apply_and_update_path(adev->audio_route,
803 "true-native-mode");
804 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530805 } else
806 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530814 int i, num_devices = 0;
815 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 if (snd_device < SND_DEVICE_MIN ||
819 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 return -EINVAL;
822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
824 ALOGE("%s: device ref cnt is already 0", __func__);
825 return -EINVAL;
826 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700829
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
831 ALOGE("%s: Invalid sound device returned", __func__);
832 return -EINVAL;
833 }
834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700836 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530837
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800838 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
839 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700840 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530841 } else if (platform_can_split_snd_device(adev->platform, snd_device,
842 &num_devices, new_snd_devices)) {
843 for (i = 0; i < num_devices; i++) {
844 disable_snd_device(adev, new_snd_devices[i]);
845 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300846 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700847 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300848 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700849
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530850 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
851 audio_extn_a2dp_stop_playback();
852
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700853 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530855 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 adev->native_playback_enabled) {
857 ALOGD("%s: %d: napb: disabling native mode in hardware",
858 __func__, __LINE__);
859 audio_route_reset_and_update_path(adev->audio_route,
860 "true-native-mode");
861 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530862 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
863 adev->asrc_mode_enabled) {
864 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
865 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
866 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530868
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200869 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700870 audio_extn_sound_trigger_update_device_status(snd_device,
871 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530872 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800873 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 return 0;
877}
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530880 struct audio_usecase *uc_info,
881 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882{
883 struct listnode *node;
884 struct audio_usecase *usecase;
885 bool switch_device[AUDIO_USECASE_MAX];
886 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530887 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 /*
889 * This function is to make sure that all the usecases that are active on
890 * the hardware codec backend are always routed to any one device that is
891 * handled by the hardware codec.
892 * For example, if low-latency and deep-buffer usecases are currently active
893 * on speaker and out_set_parameters(headset) is received on low-latency
894 * output, then we have to make sure deep-buffer is also switched to headset,
895 * because of the limitation that both the devices cannot be enabled
896 * at the same time as they share the same backend.
897 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700898 /*
899 * This call is to check if we need to force routing for a particular stream
900 * If there is a backend configuration change for the device when a
901 * new stream starts, then ADM needs to be closed and re-opened with the new
902 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800903 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700904 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800905 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
906 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
912 audio_extn_a2dp_is_force_device_switch()) {
913 force_routing = true;
914 force_restart_session = true;
915 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 ALOGD("%s:becf: force routing %d", __func__, force_routing);
917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800919 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 for (i = 0; i < AUDIO_USECASE_MAX; i++)
922 switch_device[i] = false;
923
924 list_for_each(node, &adev->usecase_list) {
925 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800926
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530927 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
928 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530929 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530930 platform_get_snd_device_name(usecase->out_snd_device),
931 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800932 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530933 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530934 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530935 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
936 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530937 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530938 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530939 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
940 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
941 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530942 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
944 platform_get_snd_device_name(usecase->out_snd_device));
945 disable_audio_route(adev, usecase);
946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530951 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
952 num_uc_to_switch);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700955 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530957 /* Make sure the previous devices to be disabled first and then enable the
958 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 }
964 }
965
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700970 }
971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 /* Re-route all the usecases on the shared backend other than the
974 specified usecase to new snd devices */
975 list_for_each(node, &adev->usecase_list) {
976 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530977 /* Update the out_snd_device only before enabling the audio route */
978 if (switch_device[usecase->id]) {
979 usecase->out_snd_device = snd_device;
980 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530981 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530982 use_case_table[usecase->id],
983 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989}
990
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530991static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 struct audio_usecase *uc_info,
993 snd_device_t snd_device)
994{
995 struct listnode *node;
996 struct audio_usecase *usecase;
997 bool switch_device[AUDIO_USECASE_MAX];
998 int i, num_uc_to_switch = 0;
999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301000 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1001 snd_device);
1002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001018 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301020 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001021 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301022 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001023 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001024 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001025 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1026 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001027 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001029 switch_device[usecase->id] = true;
1030 num_uc_to_switch++;
1031 }
1032 }
1033
1034 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001035 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301037 /* Make sure the previous devices to be disabled first and then enable the
1038 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001043 }
1044 }
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001049 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 }
1051 }
1052
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001053 /* Re-route all the usecases on the shared backend other than the
1054 specified usecase to new snd devices */
1055 list_for_each(node, &adev->usecase_list) {
1056 usecase = node_to_item(node, struct audio_usecase, list);
1057 /* Update the in_snd_device only before enabling the audio route */
1058 if (switch_device[usecase->id] ) {
1059 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001060 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301061 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001064 }
1065}
1066
Mingming Yin3a941d42016-02-17 18:08:05 -08001067static void reset_hdmi_sink_caps(struct stream_out *out) {
1068 int i = 0;
1069
1070 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1071 out->supported_channel_masks[i] = 0;
1072 }
1073 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1074 out->supported_formats[i] = 0;
1075 }
1076 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1077 out->supported_sample_rates[i] = 0;
1078 }
1079}
1080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001082static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083{
Mingming Yin3a941d42016-02-17 18:08:05 -08001084 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001085 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Mingming Yin3a941d42016-02-17 18:08:05 -08001087 reset_hdmi_sink_caps(out);
1088
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001089 /* Cache ext disp type */
1090 ret = platform_get_ext_disp_type(adev->platform);
1091 if (ret < 0) {
1092 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1093 return ret;
1094 }
1095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001098 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1101 case 6:
1102 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1103 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1104 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1105 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1107 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 break;
1109 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001110 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001111 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 break;
1113 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001114
1115 // check channel format caps
1116 i = 0;
1117 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1118 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1119 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1120 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1121 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1122 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1123 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1124 }
1125
1126 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1127 ALOGV(":%s HDMI supports DTS format", __func__);
1128 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1129 }
1130
1131 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1132 ALOGV(":%s HDMI supports DTS HD format", __func__);
1133 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1134 }
1135
1136
1137 // check sample rate caps
1138 i = 0;
1139 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1140 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1141 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1142 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1143 }
1144 }
1145
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147}
1148
Alexy Josephb1379942016-01-29 15:49:38 -08001149audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151{
1152 struct audio_usecase *usecase;
1153 struct listnode *node;
1154
1155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001157 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001158 ALOGV("%s: usecase id %d", __func__, usecase->id);
1159 return usecase->id;
1160 }
1161 }
1162 return USECASE_INVALID;
1163}
1164
Alexy Josephb1379942016-01-29 15:49:38 -08001165struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001166 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167{
1168 struct audio_usecase *usecase;
1169 struct listnode *node;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->id == uc_id)
1174 return usecase;
1175 }
1176 return NULL;
1177}
1178
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179/*
1180 * is a true native playback active
1181 */
1182bool audio_is_true_native_stream_active(struct audio_device *adev)
1183{
1184 bool active = false;
1185 int i = 0;
1186 struct listnode *node;
1187
1188 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1189 ALOGV("%s:napb: not in true mode or non hdphones device",
1190 __func__);
1191 active = false;
1192 goto exit;
1193 }
1194
1195 list_for_each(node, &adev->usecase_list) {
1196 struct audio_usecase *uc;
1197 uc = node_to_item(node, struct audio_usecase, list);
1198 struct stream_out *curr_out =
1199 (struct stream_out*) uc->stream.out;
1200
1201 if (curr_out && PCM_PLAYBACK == uc->type) {
1202 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1203 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1204 uc->id, curr_out->sample_rate,
1205 curr_out->bit_width,
1206 platform_get_snd_device_name(uc->out_snd_device));
1207
1208 if (is_offload_usecase(uc->id) &&
1209 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1210 active = true;
1211 ALOGD("%s:napb:native stream detected", __func__);
1212 }
1213 }
1214 }
1215exit:
1216 return active;
1217}
1218
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301219/*
1220 * if native DSD playback active
1221 */
1222bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1223{
1224 bool active = false;
1225 struct listnode *node = NULL;
1226 struct audio_usecase *uc = NULL;
1227 struct stream_out *curr_out = NULL;
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 uc = node_to_item(node, struct audio_usecase, list);
1231 curr_out = (struct stream_out*) uc->stream.out;
1232
1233 if (curr_out && PCM_PLAYBACK == uc->type &&
1234 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1235 active = true;
1236 ALOGV("%s:DSD playback is active", __func__);
1237 }
1238 }
1239 return active;
1240}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301241
1242static bool force_device_switch(struct audio_usecase *usecase)
1243{
1244 bool ret = false;
1245 bool is_it_true_mode = false;
1246
1247 if (is_offload_usecase(usecase->id) &&
1248 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001249 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1250 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1251 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301252 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1253 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1254 (!is_it_true_mode && adev->native_playback_enabled)){
1255 ret = true;
1256 ALOGD("napb: time to toggle native mode");
1257 }
1258 }
1259
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301260 // Force all a2dp output devices to reconfigure for proper AFE encode format
1261 if((usecase->stream.out) &&
1262 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1263 audio_extn_a2dp_is_force_device_switch()) {
1264 ALOGD("Force a2dp device switch to update new encoder config");
1265 ret = true;
1266 }
1267
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301268 return ret;
1269}
1270
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001271int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001273 snd_device_t out_snd_device = SND_DEVICE_NONE;
1274 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 struct audio_usecase *usecase = NULL;
1276 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001277 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001278 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001279 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301282 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1283
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase = get_usecase_from_list(adev, uc_id);
1285 if (usecase == NULL) {
1286 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1287 return -EINVAL;
1288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001290 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001291 (usecase->type == VOIP_CALL) ||
1292 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001293 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001294 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001295 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 usecase->devices = usecase->stream.out->devices;
1297 } else {
1298 /*
1299 * If the voice call is active, use the sound devices of voice call usecase
1300 * so that it would not result any device switch. All the usecases will
1301 * be switched to new device when select_devices() is called for voice call
1302 * usecase. This is to avoid switching devices for voice call when
1303 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001304 * choose voice call device only if the use case device is
1305 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001307 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001308 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001309 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001310 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1311 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301312 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1313 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001314 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 in_snd_device = vc_usecase->in_snd_device;
1316 out_snd_device = vc_usecase->out_snd_device;
1317 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001318 } else if (voice_extn_compress_voip_is_active(adev)) {
1319 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001320 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001321 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1322 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001323 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001324 in_snd_device = voip_usecase->in_snd_device;
1325 out_snd_device = voip_usecase->out_snd_device;
1326 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001327 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001328 hfp_ucid = audio_extn_hfp_get_usecase();
1329 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001330 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001331 in_snd_device = hfp_usecase->in_snd_device;
1332 out_snd_device = hfp_usecase->out_snd_device;
1333 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334 }
1335 if (usecase->type == PCM_PLAYBACK) {
1336 usecase->devices = usecase->stream.out->devices;
1337 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001338 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001339 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001340 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001341 if (usecase->stream.out == adev->primary_output &&
1342 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001343 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001344 select_devices(adev, adev->active_input->usecase);
1345 }
1346 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001347 } else if (usecase->type == PCM_CAPTURE) {
1348 usecase->devices = usecase->stream.in->device;
1349 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001350 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001351 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001352 if (adev->active_input &&
1353 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301354 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1355 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1356 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001357 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001358 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001359 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1360 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001361 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001362 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001363 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364 }
1365 }
1366
1367 if (out_snd_device == usecase->out_snd_device &&
1368 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301369
1370 if (!force_device_switch(usecase))
1371 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 }
1373
sangwoobc677242013-08-08 16:53:43 +09001374 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001375 out_snd_device, platform_get_snd_device_name(out_snd_device),
1376 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 /*
1379 * Limitation: While in call, to do a device switch we need to disable
1380 * and enable both RX and TX devices though one of them is same as current
1381 * device.
1382 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001383 if ((usecase->type == VOICE_CALL) &&
1384 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1385 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001386 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001387 }
1388
1389 if (((usecase->type == VOICE_CALL) ||
1390 (usecase->type == VOIP_CALL)) &&
1391 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1392 /* Disable sidetone only if voice/voip call already exists */
1393 if (voice_is_call_state_active(adev) ||
1394 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001395 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001396 }
1397
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398 /* Disable current sound devices */
1399 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 disable_audio_route(adev, usecase);
1401 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 }
1403
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001405 disable_audio_route(adev, usecase);
1406 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 }
1408
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001409 /* Applicable only on the targets that has external modem.
1410 * New device information should be sent to modem before enabling
1411 * the devices to reduce in-call device switch time.
1412 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001413 if ((usecase->type == VOICE_CALL) &&
1414 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1415 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001416 status = platform_switch_voice_call_enable_device_config(adev->platform,
1417 out_snd_device,
1418 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001419 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001420
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 /* Enable new sound devices */
1422 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001423 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001424 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 }
1426
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001427 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301428 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001429 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001430 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431
Avinash Vaish71a8b972014-07-24 15:36:33 +05301432 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001433 status = platform_switch_voice_call_device_post(adev->platform,
1434 out_snd_device,
1435 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301436 enable_audio_route_for_voice_usecases(adev, usecase);
1437 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001438
sangwoo170731f2013-06-08 15:36:36 +09001439 usecase->in_snd_device = in_snd_device;
1440 usecase->out_snd_device = out_snd_device;
1441
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301442 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001443 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301444 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001445 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301446 usecase->stream.out->flags,
1447 usecase->stream.out->format,
1448 usecase->stream.out->sample_rate,
1449 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301450 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301451 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001452 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301453 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001454
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001455 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001456
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001457 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1458 /* Enable sidetone only if other voice/voip call already exists */
1459 if (voice_is_call_state_active(adev) ||
1460 voice_extn_compress_voip_is_started(adev))
1461 voice_set_sidetone(adev, out_snd_device, true);
1462 }
1463
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001464 /* Applicable only on the targets that has external modem.
1465 * Enable device command should be sent to modem only after
1466 * enabling voice call mixer controls
1467 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001468 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001469 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1470 out_snd_device,
1471 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301472 ALOGD("%s: done",__func__);
1473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474 return status;
1475}
1476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477static int stop_input_stream(struct stream_in *in)
1478{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301479 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 struct audio_usecase *uc_info;
1481 struct audio_device *adev = in->dev;
1482
Eric Laurentc8400632013-02-14 19:04:54 -08001483 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484
Eric Laurent994a6932013-07-17 11:51:42 -07001485 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 uc_info = get_usecase_from_list(adev, in->usecase);
1488 if (uc_info == NULL) {
1489 ALOGE("%s: Could not find the usecase (%d) in the list",
1490 __func__, in->usecase);
1491 return -EINVAL;
1492 }
1493
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001494 /* Close in-call recording streams */
1495 voice_check_and_stop_incall_rec_usecase(adev, in);
1496
Eric Laurent150dbfe2013-02-27 14:31:02 -08001497 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001498 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499
1500 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001501 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001503 list_remove(&uc_info->list);
1504 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505
Eric Laurent994a6932013-07-17 11:51:42 -07001506 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 return ret;
1508}
1509
1510int start_input_stream(struct stream_in *in)
1511{
1512 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001513 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 struct audio_usecase *uc_info;
1515 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301516 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517
Mingming Yin2664a5b2015-09-03 10:53:11 -07001518 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1519 if (get_usecase_from_list(adev, usecase) == NULL)
1520 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301521 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1522 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001523
Naresh Tanniru80659832014-06-04 18:17:56 +05301524
1525 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301526 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301527 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301528 goto error_config;
1529 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301530
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001531 /* Check if source matches incall recording usecase criteria */
1532 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1533 if (ret)
1534 goto error_config;
1535 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001536 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1537
1538 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1539 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1540 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001541 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001542 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001543
Eric Laurentb23d5282013-05-14 15:27:20 -07001544 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 if (in->pcm_device_id < 0) {
1546 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1547 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001548 ret = -EINVAL;
1549 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001551
1552 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001554
1555 if (!uc_info) {
1556 ret = -ENOMEM;
1557 goto error_config;
1558 }
1559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560 uc_info->id = in->usecase;
1561 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001562 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 uc_info->devices = in->device;
1564 uc_info->in_snd_device = SND_DEVICE_NONE;
1565 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001567 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301568 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1569 adev->perf_lock_opts,
1570 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301573 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1574 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001575
1576 unsigned int flags = PCM_IN;
1577 unsigned int pcm_open_retry_count = 0;
1578
1579 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1580 flags |= PCM_MMAP | PCM_NOIRQ;
1581 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001582 } else if (in->realtime) {
1583 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 }
1585
1586 while (1) {
1587 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1588 flags, &in->config);
1589 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1590 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1591 if (in->pcm != NULL) {
1592 pcm_close(in->pcm);
1593 in->pcm = NULL;
1594 }
1595 if (pcm_open_retry_count-- == 0) {
1596 ret = -EIO;
1597 goto error_open;
1598 }
1599 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1600 continue;
1601 }
1602 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001604
1605 ALOGV("%s: pcm_prepare", __func__);
1606 ret = pcm_prepare(in->pcm);
1607 if (ret < 0) {
1608 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1609 pcm_close(in->pcm);
1610 in->pcm = NULL;
1611 goto error_open;
1612 }
1613
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001614 register_in_stream(in);
1615 if (in->realtime) {
1616 ret = pcm_start(in->pcm);
1617 if (ret < 0)
1618 goto error_open;
1619 }
1620
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301621 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001622 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001623
Eric Laurentc8400632013-02-14 19:04:54 -08001624 return ret;
1625
1626error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301627 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001629error_config:
1630 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301631 /*
1632 * sleep 50ms to allow sufficient time for kernel
1633 * drivers to recover incases like SSR.
1634 */
1635 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001636 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001637
1638 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639}
1640
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001641void lock_input_stream(struct stream_in *in)
1642{
1643 pthread_mutex_lock(&in->pre_lock);
1644 pthread_mutex_lock(&in->lock);
1645 pthread_mutex_unlock(&in->pre_lock);
1646}
1647
1648void lock_output_stream(struct stream_out *out)
1649{
1650 pthread_mutex_lock(&out->pre_lock);
1651 pthread_mutex_lock(&out->lock);
1652 pthread_mutex_unlock(&out->pre_lock);
1653}
1654
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001655/* must be called with out->lock locked */
1656static int send_offload_cmd_l(struct stream_out* out, int command)
1657{
1658 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1659
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001660 if (!cmd) {
1661 ALOGE("failed to allocate mem for command 0x%x", command);
1662 return -ENOMEM;
1663 }
1664
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001665 ALOGVV("%s %d", __func__, command);
1666
1667 cmd->cmd = command;
1668 list_add_tail(&out->offload_cmd_list, &cmd->node);
1669 pthread_cond_signal(&out->offload_cond);
1670 return 0;
1671}
1672
1673/* must be called iwth out->lock locked */
1674static void stop_compressed_output_l(struct stream_out *out)
1675{
1676 out->offload_state = OFFLOAD_STATE_IDLE;
1677 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001678 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 if (out->compr != NULL) {
1680 compress_stop(out->compr);
1681 while (out->offload_thread_blocked) {
1682 pthread_cond_wait(&out->cond, &out->lock);
1683 }
1684 }
1685}
1686
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001687bool is_offload_usecase(audio_usecase_t uc_id)
1688{
1689 unsigned int i;
1690 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1691 if (uc_id == offload_usecases[i])
1692 return true;
1693 }
1694 return false;
1695}
1696
vivek mehta446c3962015-09-14 10:57:35 -07001697static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001698{
vivek mehta446c3962015-09-14 10:57:35 -07001699 audio_usecase_t ret_uc = USECASE_INVALID;
1700 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001701 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001702 if (!adev->multi_offload_enable) {
1703 if (is_direct_pcm)
1704 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1705 else
1706 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001707
vivek mehta446c3962015-09-14 10:57:35 -07001708 pthread_mutex_lock(&adev->lock);
1709 if (get_usecase_from_list(adev, ret_uc) != NULL)
1710 ret_uc = USECASE_INVALID;
1711 pthread_mutex_unlock(&adev->lock);
1712
1713 return ret_uc;
1714 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001715
1716 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001717 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1718 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1719 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1720 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721 break;
1722 }
1723 }
vivek mehta446c3962015-09-14 10:57:35 -07001724
1725 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1726 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001727}
1728
1729static void free_offload_usecase(struct audio_device *adev,
1730 audio_usecase_t uc_id)
1731{
vivek mehta446c3962015-09-14 10:57:35 -07001732 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001733 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001734
1735 if (!adev->multi_offload_enable)
1736 return;
1737
1738 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1739 if (offload_usecases[offload_uc_index] == uc_id) {
1740 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001741 break;
1742 }
1743 }
1744 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1745}
1746
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747static void *offload_thread_loop(void *context)
1748{
1749 struct stream_out *out = (struct stream_out *) context;
1750 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001751 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1754 set_sched_policy(0, SP_FOREGROUND);
1755 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1756
1757 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001758 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 for (;;) {
1760 struct offload_cmd *cmd = NULL;
1761 stream_callback_event_t event;
1762 bool send_callback = false;
1763
1764 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1765 __func__, list_empty(&out->offload_cmd_list),
1766 out->offload_state);
1767 if (list_empty(&out->offload_cmd_list)) {
1768 ALOGV("%s SLEEPING", __func__);
1769 pthread_cond_wait(&out->offload_cond, &out->lock);
1770 ALOGV("%s RUNNING", __func__);
1771 continue;
1772 }
1773
1774 item = list_head(&out->offload_cmd_list);
1775 cmd = node_to_item(item, struct offload_cmd, node);
1776 list_remove(item);
1777
1778 ALOGVV("%s STATE %d CMD %d out->compr %p",
1779 __func__, out->offload_state, cmd->cmd, out->compr);
1780
1781 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1782 free(cmd);
1783 break;
1784 }
1785
1786 if (out->compr == NULL) {
1787 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001788 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 pthread_cond_signal(&out->cond);
1790 continue;
1791 }
1792 out->offload_thread_blocked = true;
1793 pthread_mutex_unlock(&out->lock);
1794 send_callback = false;
1795 switch(cmd->cmd) {
1796 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001797 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001799 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 send_callback = true;
1801 event = STREAM_CBK_EVENT_WRITE_READY;
1802 break;
1803 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001804 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301805 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001806 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301807 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001808 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301809 if (ret < 0)
1810 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301811 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301812 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001813 compress_drain(out->compr);
1814 else
1815 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301816 if (ret != -ENETRESET) {
1817 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301818 pthread_mutex_lock(&out->lock);
1819 out->send_new_metadata = 1;
1820 out->send_next_track_params = true;
1821 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301822 event = STREAM_CBK_EVENT_DRAIN_READY;
1823 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1824 } else
1825 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001826 break;
1827 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001828 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001830 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 send_callback = true;
1832 event = STREAM_CBK_EVENT_DRAIN_READY;
1833 break;
1834 default:
1835 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1836 break;
1837 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001838 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 out->offload_thread_blocked = false;
1840 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001841 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001842 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001843 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001844 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 free(cmd);
1846 }
1847
1848 pthread_cond_signal(&out->cond);
1849 while (!list_empty(&out->offload_cmd_list)) {
1850 item = list_head(&out->offload_cmd_list);
1851 list_remove(item);
1852 free(node_to_item(item, struct offload_cmd, node));
1853 }
1854 pthread_mutex_unlock(&out->lock);
1855
1856 return NULL;
1857}
1858
1859static int create_offload_callback_thread(struct stream_out *out)
1860{
1861 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1862 list_init(&out->offload_cmd_list);
1863 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1864 offload_thread_loop, out);
1865 return 0;
1866}
1867
1868static int destroy_offload_callback_thread(struct stream_out *out)
1869{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001870 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001871 stop_compressed_output_l(out);
1872 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1873
1874 pthread_mutex_unlock(&out->lock);
1875 pthread_join(out->offload_thread, (void **) NULL);
1876 pthread_cond_destroy(&out->offload_cond);
1877
1878 return 0;
1879}
1880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881static int stop_output_stream(struct stream_out *out)
1882{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301883 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 struct audio_usecase *uc_info;
1885 struct audio_device *adev = out->dev;
1886
Eric Laurent994a6932013-07-17 11:51:42 -07001887 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 uc_info = get_usecase_from_list(adev, out->usecase);
1890 if (uc_info == NULL) {
1891 ALOGE("%s: Could not find the usecase (%d) in the list",
1892 __func__, out->usecase);
1893 return -EINVAL;
1894 }
1895
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001896 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301897 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001898 if (adev->visualizer_stop_output != NULL)
1899 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001900
1901 audio_extn_dts_remove_state_notifier_node(out->usecase);
1902
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001903 if (adev->offload_effects_stop_output != NULL)
1904 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1905 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001906
Eric Laurent150dbfe2013-02-27 14:31:02 -08001907 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001908 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909
1910 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001911 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001913 list_remove(&uc_info->list);
1914 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001916 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301917 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001918 ALOGV("Disable passthrough , reset mixer to pcm");
1919 /* NO_PASSTHROUGH */
1920 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001921 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001922 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1923 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001924
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301925 /* Must be called after removing the usecase from list */
1926 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301927 audio_extn_keep_alive_start();
1928
Eric Laurent994a6932013-07-17 11:51:42 -07001929 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 return ret;
1931}
1932
1933int start_output_stream(struct stream_out *out)
1934{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 struct audio_usecase *uc_info;
1937 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301938 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001940 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1941 ret = -EINVAL;
1942 goto error_config;
1943 }
1944
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301945 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1946 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1947 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301948
Naresh Tanniru80659832014-06-04 18:17:56 +05301949 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301950 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301951 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301952 goto error_config;
1953 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301954
Eric Laurentb23d5282013-05-14 15:27:20 -07001955 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 if (out->pcm_device_id < 0) {
1957 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1958 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001959 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001960 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 }
1962
1963 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001964
1965 if (!uc_info) {
1966 ret = -ENOMEM;
1967 goto error_config;
1968 }
1969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 uc_info->id = out->usecase;
1971 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001972 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001973 uc_info->devices = out->devices;
1974 uc_info->in_snd_device = SND_DEVICE_NONE;
1975 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001976 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301978 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1979 adev->perf_lock_opts,
1980 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301981
1982 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1983 audio_extn_keep_alive_stop();
1984 if (audio_extn_passthru_is_enabled() &&
1985 audio_extn_passthru_is_passthrough_stream(out)) {
1986 audio_extn_passthru_on_start(out);
1987 audio_extn_passthru_update_stream_configuration(adev, out);
1988 }
1989 }
1990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001991 select_devices(adev, out->usecase);
1992
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001993 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1994 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001996 unsigned int flags = PCM_OUT;
1997 unsigned int pcm_open_retry_count = 0;
1998 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1999 flags |= PCM_MMAP | PCM_NOIRQ;
2000 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002001 } else if (out->realtime) {
2002 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002003 } else
2004 flags |= PCM_MONOTONIC;
2005
2006 while (1) {
2007 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2008 flags, &out->config);
2009 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2010 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2011 if (out->pcm != NULL) {
2012 pcm_close(out->pcm);
2013 out->pcm = NULL;
2014 }
2015 if (pcm_open_retry_count-- == 0) {
2016 ret = -EIO;
2017 goto error_open;
2018 }
2019 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2020 continue;
2021 }
2022 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002024
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002025 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2026 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002027
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002028 ALOGV("%s: pcm_prepare", __func__);
2029 if (pcm_is_ready(out->pcm)) {
2030 ret = pcm_prepare(out->pcm);
2031 if (ret < 0) {
2032 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2033 pcm_close(out->pcm);
2034 out->pcm = NULL;
2035 goto error_open;
2036 }
2037 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002039 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2040 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002042 out->compr = compress_open(adev->snd_card,
2043 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 COMPRESS_IN, &out->compr_config);
2045 if (out->compr && !is_compress_ready(out->compr)) {
2046 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2047 compress_close(out->compr);
2048 out->compr = NULL;
2049 ret = -EIO;
2050 goto error_open;
2051 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302052 /* compress_open sends params of the track, so reset the flag here */
2053 out->is_compr_metadata_avail = false;
2054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 if (out->offload_callback)
2056 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002057
Fred Oh3f43e742015-03-04 18:42:34 -08002058 /* Since small bufs uses blocking writes, a write will be blocked
2059 for the default max poll time (20s) in the event of an SSR.
2060 Reduce the poll time to observe and deal with SSR faster.
2061 */
Ashish Jain5106d362016-05-11 19:23:33 +05302062 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002063 compress_set_max_poll_wait(out->compr, 1000);
2064 }
2065
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002066 audio_extn_dts_create_state_notifier_node(out->usecase);
2067 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2068 popcount(out->channel_mask),
2069 out->playback_started);
2070
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002071#ifdef DS1_DOLBY_DDP_ENABLED
2072 if (audio_extn_is_dolby_format(out->format))
2073 audio_extn_dolby_send_ddp_endp_params(adev);
2074#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302075 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002076 if (adev->visualizer_start_output != NULL)
2077 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2078 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302079 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002080 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002083
2084 if (ret == 0) {
2085 register_out_stream(out);
2086 if (out->realtime) {
2087 ret = pcm_start(out->pcm);
2088 if (ret < 0)
2089 goto error_open;
2090 }
2091 }
2092
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302093 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002094 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002095
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002096 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302098 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002100error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302101 /*
2102 * sleep 50ms to allow sufficient time for kernel
2103 * drivers to recover incases like SSR.
2104 */
2105 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002106 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107}
2108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109static int check_input_parameters(uint32_t sample_rate,
2110 audio_format_t format,
2111 int channel_count)
2112{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002113 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302115 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2116 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2117 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002118 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302119 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002120
2121 switch (channel_count) {
2122 case 1:
2123 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302124 case 3:
2125 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002126 case 6:
2127 break;
2128 default:
2129 ret = -EINVAL;
2130 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131
2132 switch (sample_rate) {
2133 case 8000:
2134 case 11025:
2135 case 12000:
2136 case 16000:
2137 case 22050:
2138 case 24000:
2139 case 32000:
2140 case 44100:
2141 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302142 case 96000:
2143 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 break;
2145 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002146 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 }
2148
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002149 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150}
2151
2152static size_t get_input_buffer_size(uint32_t sample_rate,
2153 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002154 int channel_count,
2155 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156{
2157 size_t size = 0;
2158
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002159 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2160 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002162 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002163 if (is_low_latency)
2164 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302165
2166 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002168 /* make sure the size is multiple of 32 bytes
2169 * At 48 kHz mono 16-bit PCM:
2170 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2171 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2172 */
2173 size += 0x1f;
2174 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002175
2176 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177}
2178
Ashish Jain5106d362016-05-11 19:23:33 +05302179static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2180{
2181 uint64_t actual_frames_rendered = 0;
2182 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2183
2184 /* This adjustment accounts for buffering after app processor.
2185 * It is based on estimated DSP latency per use case, rather than exact.
2186 */
2187 int64_t platform_latency = platform_render_latency(out->usecase) *
2188 out->sample_rate / 1000000LL;
2189
2190 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2191 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2192 * hence only estimate.
2193 */
2194 int64_t signed_frames = out->written - kernel_buffer_size;
2195
2196 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2197
2198 if (signed_frames > 0)
2199 actual_frames_rendered = signed_frames;
2200
2201 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2202 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2203 (long long int)out->written, (int)kernel_buffer_size,
2204 audio_bytes_per_sample(out->compr_config.codec->format),
2205 popcount(out->channel_mask));
2206
2207 return actual_frames_rendered;
2208}
2209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2211{
2212 struct stream_out *out = (struct stream_out *)stream;
2213
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215}
2216
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002217static int out_set_sample_rate(struct audio_stream *stream __unused,
2218 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219{
2220 return -ENOSYS;
2221}
2222
2223static size_t out_get_buffer_size(const struct audio_stream *stream)
2224{
2225 struct stream_out *out = (struct stream_out *)stream;
2226
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002227 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002229 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2230 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302231 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302232 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002234 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002235 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236}
2237
2238static uint32_t out_get_channels(const struct audio_stream *stream)
2239{
2240 struct stream_out *out = (struct stream_out *)stream;
2241
2242 return out->channel_mask;
2243}
2244
2245static audio_format_t out_get_format(const struct audio_stream *stream)
2246{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 struct stream_out *out = (struct stream_out *)stream;
2248
2249 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250}
2251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002252static int out_set_format(struct audio_stream *stream __unused,
2253 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return -ENOSYS;
2256}
2257
2258static int out_standby(struct audio_stream *stream)
2259{
2260 struct stream_out *out = (struct stream_out *)stream;
2261 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302263 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2264 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002266 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002268 if (adev->adm_deregister_stream)
2269 adev->adm_deregister_stream(adev->adm_data, out->handle);
2270
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002271 if (is_offload_usecase(out->usecase))
2272 stop_compressed_output_l(out);
2273
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002274 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002276 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2277 voice_extn_compress_voip_close_output_stream(stream);
2278 pthread_mutex_unlock(&adev->lock);
2279 pthread_mutex_unlock(&out->lock);
2280 ALOGD("VOIP output entered standby");
2281 return 0;
2282 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002283 if (out->pcm) {
2284 pcm_close(out->pcm);
2285 out->pcm = NULL;
2286 }
2287 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002288 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302289 out->send_next_track_params = false;
2290 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002291 out->gapless_mdata.encoder_delay = 0;
2292 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 if (out->compr != NULL) {
2294 compress_close(out->compr);
2295 out->compr = NULL;
2296 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002299 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 }
2301 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302302 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 return 0;
2304}
2305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002306static int out_dump(const struct audio_stream *stream __unused,
2307 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308{
2309 return 0;
2310}
2311
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002312static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2313{
2314 int ret = 0;
2315 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002316
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002317 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002318 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002319 return -EINVAL;
2320 }
2321
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302322 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002323
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002324 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2325 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302326 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002327 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002328 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2329 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302330 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002331 }
2332
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002333 ALOGV("%s new encoder delay %u and padding %u", __func__,
2334 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2335
2336 return 0;
2337}
2338
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002339static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2340{
2341 return out == adev->primary_output || out == adev->voice_tx_output;
2342}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2345{
2346 struct stream_out *out = (struct stream_out *)stream;
2347 struct audio_device *adev = out->dev;
2348 struct str_parms *parms;
2349 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002350 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351
sangwoobc677242013-08-08 16:53:43 +09002352 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002353 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302355 if (!parms)
2356 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002357 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2358 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002360 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002361 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002363 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002364 * When HDMI cable is unplugged the music playback is paused and
2365 * the policy manager sends routing=0. But the audioflinger continues
2366 * to write data until standby time (3sec). As the HDMI core is
2367 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002368 * Avoid this by routing audio to speaker until standby.
2369 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002370 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2371 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302372 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002373 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2374 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002375 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302376 /*
2377 * When A2DP is disconnected the
2378 * music playback is paused and the policy manager sends routing=0
2379 * But the audioflingercontinues to write data until standby time
2380 * (3sec). As BT is turned off, the write gets blocked.
2381 * Avoid this by routing audio to speaker until standby.
2382 */
2383 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2384 (val == AUDIO_DEVICE_NONE)) {
2385 val = AUDIO_DEVICE_OUT_SPEAKER;
2386 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002387
2388 /*
2389 * select_devices() call below switches all the usecases on the same
2390 * backend to the new device. Refer to check_usecases_codec_backend() in
2391 * the select_devices(). But how do we undo this?
2392 *
2393 * For example, music playback is active on headset (deep-buffer usecase)
2394 * and if we go to ringtones and select a ringtone, low-latency usecase
2395 * will be started on headset+speaker. As we can't enable headset+speaker
2396 * and headset devices at the same time, select_devices() switches the music
2397 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2398 * So when the ringtone playback is completed, how do we undo the same?
2399 *
2400 * We are relying on the out_set_parameters() call on deep-buffer output,
2401 * once the ringtone playback is ended.
2402 * NOTE: We should not check if the current devices are same as new devices.
2403 * Because select_devices() must be called to switch back the music
2404 * playback to headset.
2405 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002406 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002407 audio_devices_t new_dev = val;
2408 bool same_dev = out->devices == new_dev;
2409 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002410
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002411 if (output_drives_call(adev, out)) {
2412 if(!voice_is_in_call(adev)) {
2413 if (adev->mode == AUDIO_MODE_IN_CALL) {
2414 adev->current_call_output = out;
2415 ret = voice_start_call(adev);
2416 }
2417 } else {
2418 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002419 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002420 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002421 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002422
2423 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002424 if (!same_dev) {
2425 ALOGV("update routing change");
2426 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302427 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2428 adev->perf_lock_opts,
2429 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002430 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002431 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302432 if (!same_dev)
2433 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002434 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002435 }
2436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002438 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002440
2441 if (out == adev->primary_output) {
2442 pthread_mutex_lock(&adev->lock);
2443 audio_extn_set_parameters(adev, parms);
2444 pthread_mutex_unlock(&adev->lock);
2445 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002446 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002447 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002448 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002449
2450 audio_extn_dts_create_state_notifier_node(out->usecase);
2451 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2452 popcount(out->channel_mask),
2453 out->playback_started);
2454
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002455 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002456 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302459error:
Eric Laurent994a6932013-07-17 11:51:42 -07002460 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 return ret;
2462}
2463
2464static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002468 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 char value[256];
2470 struct str_parms *reply = str_parms_create();
2471 size_t i, j;
2472 int ret;
2473 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002474
2475 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002476 if (reply) {
2477 str_parms_destroy(reply);
2478 }
2479 if (query) {
2480 str_parms_destroy(query);
2481 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002482 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2483 return NULL;
2484 }
2485
Eric Laurent994a6932013-07-17 11:51:42 -07002486 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2488 if (ret >= 0) {
2489 value[0] = '\0';
2490 i = 0;
2491 while (out->supported_channel_masks[i] != 0) {
2492 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2493 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2494 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002495 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002497 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 first = false;
2499 break;
2500 }
2501 }
2502 i++;
2503 }
2504 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2505 str = str_parms_to_str(reply);
2506 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002507 voice_extn_out_get_parameters(out, query, reply);
2508 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002509 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002510 free(str);
2511 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002514
Alexy Joseph62142aa2015-11-16 15:10:34 -08002515
2516 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2517 if (ret >= 0) {
2518 value[0] = '\0';
2519 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2520 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302521 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002522 } else {
2523 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302524 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002525 }
2526 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002527 if (str)
2528 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002529 str = str_parms_to_str(reply);
2530 }
2531
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002532 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2533 if (ret >= 0) {
2534 value[0] = '\0';
2535 i = 0;
2536 first = true;
2537 while (out->supported_formats[i] != 0) {
2538 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2539 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2540 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002541 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002542 }
2543 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2544 first = false;
2545 break;
2546 }
2547 }
2548 i++;
2549 }
2550 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002551 if (str)
2552 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002553 str = str_parms_to_str(reply);
2554 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002555
2556 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2557 if (ret >= 0) {
2558 value[0] = '\0';
2559 i = 0;
2560 first = true;
2561 while (out->supported_sample_rates[i] != 0) {
2562 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2563 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2564 if (!first) {
2565 strlcat(value, "|", sizeof(value));
2566 }
2567 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2568 first = false;
2569 break;
2570 }
2571 }
2572 i++;
2573 }
2574 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2575 if (str)
2576 free(str);
2577 str = str_parms_to_str(reply);
2578 }
2579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 str_parms_destroy(query);
2581 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002582 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 return str;
2584}
2585
2586static uint32_t out_get_latency(const struct audio_stream_out *stream)
2587{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002588 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002590 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591
Alexy Josephaa54c872014-12-03 02:46:47 -08002592 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002593 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002594 } else if (out->realtime) {
2595 // since the buffer won't be filled up faster than realtime,
2596 // return a smaller number
2597 if (out->config.rate)
2598 period_ms = (out->af_period_multiplier * out->config.period_size *
2599 1000) / (out->config.rate);
2600 else
2601 period_ms = 0;
2602 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002603 } else {
2604 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002605 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002606 }
2607
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302608 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002609 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610}
2611
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302612static float AmpToDb(float amplification)
2613{
2614 if (amplification == 0) {
2615 return DSD_VOLUME_MIN_DB;
2616 }
2617 return 20 * log10(amplification);
2618}
2619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620static int out_set_volume(struct audio_stream_out *stream, float left,
2621 float right)
2622{
Eric Laurenta9024de2013-04-04 09:19:12 -07002623 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 int volume[2];
2625
Eric Laurenta9024de2013-04-04 09:19:12 -07002626 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2627 /* only take left channel into account: the API is for stereo anyway */
2628 out->muted = (left == 0.0f);
2629 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002630 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302631 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002632 /*
2633 * Set mute or umute on HDMI passthrough stream.
2634 * Only take left channel into account.
2635 * Mute is 0 and unmute 1
2636 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302637 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302638 } else if (out->format == AUDIO_FORMAT_DSD){
2639 char mixer_ctl_name[128] = "DSD Volume";
2640 struct audio_device *adev = out->dev;
2641 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2642
2643 if (!ctl) {
2644 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2645 __func__, mixer_ctl_name);
2646 return -EINVAL;
2647 }
2648 volume[0] = (int)(AmpToDb(left));
2649 volume[1] = (int)(AmpToDb(right));
2650 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2651 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002652 } else {
2653 char mixer_ctl_name[128];
2654 struct audio_device *adev = out->dev;
2655 struct mixer_ctl *ctl;
2656 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002657 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002659 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2660 "Compress Playback %d Volume", pcm_device_id);
2661 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2662 if (!ctl) {
2663 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2664 __func__, mixer_ctl_name);
2665 return -EINVAL;
2666 }
2667 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2668 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2669 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2670 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002672 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 return -ENOSYS;
2675}
2676
2677static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2678 size_t bytes)
2679{
2680 struct stream_out *out = (struct stream_out *)stream;
2681 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302682 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002683 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002685 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302686
Naresh Tanniru80659832014-06-04 18:17:56 +05302687 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002688
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302689 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302690 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302691 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2692 pthread_mutex_unlock(&out->lock);
2693 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302694 } else {
2695 /* increase written size during SSR to avoid mismatch
2696 * with the written frames count in AF
2697 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002698 // bytes per frame
2699 size_t bpf = audio_bytes_per_sample(out->format) *
2700 audio_channel_count_from_out_mask(out->channel_mask);
2701 if (bpf != 0)
2702 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302703 ALOGD(" %s: sound card is not active/SSR state", __func__);
2704 ret= -EIO;
2705 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302706 }
2707 }
2708
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302709 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302710 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2711 if (audio_bytes_per_sample(out->format) != 0)
2712 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2713 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302714 goto exit;
2715 }
2716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002718 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002719 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002720 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2721 ret = voice_extn_compress_voip_start_output_stream(out);
2722 else
2723 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002724 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002725 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002727 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 goto exit;
2729 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002730
2731 if (last_known_cal_step != -1) {
2732 ALOGD("%s: retry previous failed cal level set", __func__);
2733 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736
Ashish Jain81eb2a82015-05-13 10:52:34 +05302737 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002738 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302739 adev->is_channel_status_set = true;
2740 }
2741
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002742 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002743 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002744 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002745 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002746 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2747 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302748 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2749 ALOGD("copl(%p):send next track params in gapless", out);
2750 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2751 out->send_next_track_params = false;
2752 out->is_compr_metadata_avail = false;
2753 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002754 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302755 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302756 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002757
Ashish Jain83a6cc22016-06-28 14:34:17 +05302758 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302759 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302760 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302761 pthread_mutex_unlock(&out->lock);
2762 return -EINVAL;
2763 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302764 audio_format_t dst_format = out->hal_op_format;
2765 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302766
2767 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2768 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2769
Ashish Jain83a6cc22016-06-28 14:34:17 +05302770 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302771 dst_format,
2772 buffer,
2773 src_format,
2774 frames);
2775
Ashish Jain83a6cc22016-06-28 14:34:17 +05302776 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302777 bytes_to_write);
2778
2779 /*Convert written bytes in audio flinger format*/
2780 if (ret > 0)
2781 ret = ((ret * format_to_bitwidth_table[out->format]) /
2782 format_to_bitwidth_table[dst_format]);
2783 }
2784 } else
2785 ret = compress_write(out->compr, buffer, bytes);
2786
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302787 if (ret < 0)
2788 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302789 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302790 /*msg to cb thread only if non blocking write is enabled*/
2791 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302792 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302794 } else if (-ENETRESET == ret) {
2795 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2796 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2797 pthread_mutex_unlock(&out->lock);
2798 out_standby(&out->stream.common);
2799 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 }
Ashish Jain5106d362016-05-11 19:23:33 +05302801 if ( ret == (ssize_t)bytes && !out->non_blocking)
2802 out->written += bytes;
2803
Naresh Tanniru80659832014-06-04 18:17:56 +05302804 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002806 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 out->playback_started = 1;
2808 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002809
2810 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2811 popcount(out->channel_mask),
2812 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 }
2814 pthread_mutex_unlock(&out->lock);
2815 return ret;
2816 } else {
2817 if (out->pcm) {
2818 if (out->muted)
2819 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002820
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302821 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002822
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002823 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002824
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002825 if (out->config.rate)
2826 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2827 out->config.rate;
2828
2829 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2830
2831 request_out_focus(out, ns);
2832
2833 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002834 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002835 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302836 out->convert_buffer != NULL) {
2837
2838 memcpy_by_audio_format(out->convert_buffer,
2839 out->hal_op_format,
2840 buffer,
2841 out->hal_ip_format,
2842 out->config.period_size * out->config.channels);
2843
2844 ret = pcm_write(out->pcm, out->convert_buffer,
2845 (out->config.period_size *
2846 out->config.channels *
2847 format_to_bitwidth_table[out->hal_op_format]));
2848 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002849 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302850 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002851
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002852 release_out_focus(out);
2853
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302854 if (ret < 0)
2855 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302856 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2857 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2858 else
2859 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 }
2862
2863exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302864 /* ToDo: There may be a corner case when SSR happens back to back during
2865 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302866 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302867 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302868 }
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 pthread_mutex_unlock(&out->lock);
2871
2872 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002873 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002874 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302875 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302876 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302877 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302878 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302879 out->standby = true;
2880 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302882 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302883 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 }
2885 return bytes;
2886}
2887
2888static int out_get_render_position(const struct audio_stream_out *stream,
2889 uint32_t *dsp_frames)
2890{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302892 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002893
2894 if (dsp_frames == NULL)
2895 return -EINVAL;
2896
2897 *dsp_frames = 0;
2898 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002899 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302900
2901 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2902 * this operation and adev_close_output_stream(where out gets reset).
2903 */
2904 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2905 *dsp_frames = get_actual_pcm_frames_rendered(out);
2906 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2907 return 0;
2908 }
2909
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002910 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302911 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302912 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302914 if (ret < 0)
2915 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302917 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 }
2919 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302920 if (-ENETRESET == ret) {
2921 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2922 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2923 return -EINVAL;
2924 } else if(ret < 0) {
2925 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2926 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302927 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2928 /*
2929 * Handle corner case where compress session is closed during SSR
2930 * and timestamp is queried
2931 */
2932 ALOGE(" ERROR: sound card not active, return error");
2933 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302934 } else {
2935 return 0;
2936 }
Zhou Song32a556e2015-05-05 10:46:56 +08002937 } else if (audio_is_linear_pcm(out->format)) {
2938 *dsp_frames = out->written;
2939 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 } else
2941 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942}
2943
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002944static int out_add_audio_effect(const struct audio_stream *stream __unused,
2945 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946{
2947 return 0;
2948}
2949
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002950static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2951 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952{
2953 return 0;
2954}
2955
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002956static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2957 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958{
2959 return -EINVAL;
2960}
2961
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002962static int out_get_presentation_position(const struct audio_stream_out *stream,
2963 uint64_t *frames, struct timespec *timestamp)
2964{
2965 struct stream_out *out = (struct stream_out *)stream;
2966 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002967 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002968
Ashish Jain5106d362016-05-11 19:23:33 +05302969 /* below piece of code is not guarded against any lock because audioFliner serializes
2970 * this operation and adev_close_output_stream( where out gets reset).
2971 */
2972 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2973 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2974 *frames = get_actual_pcm_frames_rendered(out);
2975 /* this is the best we can do */
2976 clock_gettime(CLOCK_MONOTONIC, timestamp);
2977 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2978 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2979 return 0;
2980 }
2981
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002982 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002983
Ashish Jain5106d362016-05-11 19:23:33 +05302984 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2985 ret = compress_get_tstamp(out->compr, &dsp_frames,
2986 &out->sample_rate);
2987 ALOGVV("%s rendered frames %ld sample_rate %d",
2988 __func__, dsp_frames, out->sample_rate);
2989 *frames = dsp_frames;
2990 if (ret < 0)
2991 ret = -errno;
2992 if (-ENETRESET == ret) {
2993 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2994 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2995 ret = -EINVAL;
2996 } else
2997 ret = 0;
2998 /* this is the best we can do */
2999 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003000 } else {
3001 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003002 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003003 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3004 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003005 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003006 // This adjustment accounts for buffering after app processor.
3007 // It is based on estimated DSP latency per use case, rather than exact.
3008 signed_frames -=
3009 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3010
Eric Laurent949a0892013-09-20 09:20:13 -07003011 // It would be unusual for this value to be negative, but check just in case ...
3012 if (signed_frames >= 0) {
3013 *frames = signed_frames;
3014 ret = 0;
3015 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003016 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303017 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3018 *frames = out->written;
3019 clock_gettime(CLOCK_MONOTONIC, timestamp);
3020 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003021 }
3022 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003023 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003024 return ret;
3025}
3026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027static int out_set_callback(struct audio_stream_out *stream,
3028 stream_callback_t callback, void *cookie)
3029{
3030 struct stream_out *out = (struct stream_out *)stream;
3031
3032 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003033 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 out->offload_callback = callback;
3035 out->offload_cookie = cookie;
3036 pthread_mutex_unlock(&out->lock);
3037 return 0;
3038}
3039
3040static int out_pause(struct audio_stream_out* stream)
3041{
3042 struct stream_out *out = (struct stream_out *)stream;
3043 int status = -ENOSYS;
3044 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003045 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003046 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303049 struct audio_device *adev = out->dev;
3050 int snd_scard_state = get_snd_card_state(adev);
3051
3052 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3053 status = compress_pause(out->compr);
3054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003056
Mingming Yin21854652016-04-13 11:54:02 -07003057 if (audio_extn_passthru_is_active()) {
3058 ALOGV("offload use case, pause passthru");
3059 audio_extn_passthru_on_pause(out);
3060 }
3061
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303062 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003063 audio_extn_dts_notify_playback_state(out->usecase, 0,
3064 out->sample_rate, popcount(out->channel_mask),
3065 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 }
3067 pthread_mutex_unlock(&out->lock);
3068 }
3069 return status;
3070}
3071
3072static int out_resume(struct audio_stream_out* stream)
3073{
3074 struct stream_out *out = (struct stream_out *)stream;
3075 int status = -ENOSYS;
3076 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003077 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003078 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003080 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303082 struct audio_device *adev = out->dev;
3083 int snd_scard_state = get_snd_card_state(adev);
3084
Mingming Yin21854652016-04-13 11:54:02 -07003085 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3086 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3087 pthread_mutex_lock(&out->dev->lock);
3088 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003089 pthread_mutex_unlock(&out->dev->lock);
3090 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303091 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003092 }
3093 if (!status) {
3094 out->offload_state = OFFLOAD_STATE_PLAYING;
3095 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303096 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003097 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3098 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 }
3100 pthread_mutex_unlock(&out->lock);
3101 }
3102 return status;
3103}
3104
3105static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3106{
3107 struct stream_out *out = (struct stream_out *)stream;
3108 int status = -ENOSYS;
3109 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003110 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003111 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3113 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3114 else
3115 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3116 pthread_mutex_unlock(&out->lock);
3117 }
3118 return status;
3119}
3120
3121static int out_flush(struct audio_stream_out* stream)
3122{
3123 struct stream_out *out = (struct stream_out *)stream;
3124 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003126 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003127 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303129 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003131 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003132 return 0;
3133 }
3134 return -ENOSYS;
3135}
3136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137/** audio_stream_in implementation **/
3138static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3139{
3140 struct stream_in *in = (struct stream_in *)stream;
3141
3142 return in->config.rate;
3143}
3144
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003145static int in_set_sample_rate(struct audio_stream *stream __unused,
3146 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147{
3148 return -ENOSYS;
3149}
3150
3151static size_t in_get_buffer_size(const struct audio_stream *stream)
3152{
3153 struct stream_in *in = (struct stream_in *)stream;
3154
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003155 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3156 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003157 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3158 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003160 return in->config.period_size * in->af_period_multiplier *
3161 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162}
3163
3164static uint32_t in_get_channels(const struct audio_stream *stream)
3165{
3166 struct stream_in *in = (struct stream_in *)stream;
3167
3168 return in->channel_mask;
3169}
3170
3171static audio_format_t in_get_format(const struct audio_stream *stream)
3172{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003173 struct stream_in *in = (struct stream_in *)stream;
3174
3175 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176}
3177
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003178static int in_set_format(struct audio_stream *stream __unused,
3179 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
3181 return -ENOSYS;
3182}
3183
3184static int in_standby(struct audio_stream *stream)
3185{
3186 struct stream_in *in = (struct stream_in *)stream;
3187 struct audio_device *adev = in->dev;
3188 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303189 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3190 stream, in->usecase, use_case_table[in->usecase]);
3191
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003192 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003193 if (!in->standby && in->is_st_session) {
3194 ALOGD("%s: sound trigger pcm stop lab", __func__);
3195 audio_extn_sound_trigger_stop_lab(in);
3196 in->standby = 1;
3197 }
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003200 if (adev->adm_deregister_stream)
3201 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3202
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003203 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003205 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3206 voice_extn_compress_voip_close_input_stream(stream);
3207 ALOGD("VOIP input entered standby");
3208 } else {
3209 if (in->pcm) {
3210 pcm_close(in->pcm);
3211 in->pcm = NULL;
3212 }
3213 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003214 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003215 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 }
3217 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003218 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 return status;
3220}
3221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003222static int in_dump(const struct audio_stream *stream __unused,
3223 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224{
3225 return 0;
3226}
3227
3228static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3229{
3230 struct stream_in *in = (struct stream_in *)stream;
3231 struct audio_device *adev = in->dev;
3232 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003234 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303236 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 parms = str_parms_create_str(kvpairs);
3238
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303239 if (!parms)
3240 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003241 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003242 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003243
3244 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3245 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 val = atoi(value);
3247 /* no audio source uses val == 0 */
3248 if ((in->source != val) && (val != 0)) {
3249 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003250 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3251 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3252 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003253 (in->config.rate == 8000 || in->config.rate == 16000 ||
3254 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003255 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003256 err = voice_extn_compress_voip_open_input_stream(in);
3257 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003258 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003259 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003260 }
3261 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 }
3263 }
3264
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003265 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3266 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003268 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 in->device = val;
3270 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003271 if (!in->standby && !in->is_st_session) {
3272 ALOGV("update input routing change");
3273 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003274 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 }
3277 }
3278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003280 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281
3282 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303283error:
Eric Laurent994a6932013-07-17 11:51:42 -07003284 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 return ret;
3286}
3287
3288static char* in_get_parameters(const struct audio_stream *stream,
3289 const char *keys)
3290{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003291 struct stream_in *in = (struct stream_in *)stream;
3292 struct str_parms *query = str_parms_create_str(keys);
3293 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003294 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003295
3296 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003297 if (reply) {
3298 str_parms_destroy(reply);
3299 }
3300 if (query) {
3301 str_parms_destroy(query);
3302 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003303 ALOGE("in_get_parameters: failed to create query or reply");
3304 return NULL;
3305 }
3306
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003307 ALOGV("%s: enter: keys - %s", __func__, keys);
3308
3309 voice_extn_in_get_parameters(in, query, reply);
3310
3311 str = str_parms_to_str(reply);
3312 str_parms_destroy(query);
3313 str_parms_destroy(reply);
3314
3315 ALOGV("%s: exit: returns - %s", __func__, str);
3316 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003319static int in_set_gain(struct audio_stream_in *stream __unused,
3320 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
3322 return 0;
3323}
3324
3325static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3326 size_t bytes)
3327{
3328 struct stream_in *in = (struct stream_in *)stream;
3329 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303330 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303331 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303332 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003334 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303335
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003336 if (in->is_st_session) {
3337 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3338 /* Read from sound trigger HAL */
3339 audio_extn_sound_trigger_read(in, buffer, bytes);
3340 pthread_mutex_unlock(&in->lock);
3341 return bytes;
3342 }
3343
Ashish Jainbbce4322016-02-16 13:25:27 +05303344 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003345 ALOGD(" %s: sound card is not active/SSR state", __func__);
3346 ret= -EIO;;
3347 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303348 }
3349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003351 pthread_mutex_lock(&adev->lock);
3352 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3353 ret = voice_extn_compress_voip_start_input_stream(in);
3354 else
3355 ret = start_input_stream(in);
3356 pthread_mutex_unlock(&adev->lock);
3357 if (ret != 0) {
3358 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 }
3360 in->standby = 0;
3361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003363 // what's the duration requested by the client?
3364 long ns = 0;
3365
3366 if (in->config.rate)
3367 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3368 in->config.rate;
3369
3370 request_in_focus(in, ns);
3371 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303374 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003375 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303376 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003377 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003378 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003379 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303380 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003381 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303382 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3383 if (bytes % 4 == 0) {
3384 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3385 int_buf_stream = buffer;
3386 for (size_t itt=0; itt < bytes/4 ; itt++) {
3387 int_buf_stream[itt] >>= 8;
3388 }
3389 } else {
3390 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3391 ret = -EINVAL;
3392 goto exit;
3393 }
3394 } if (ret < 0) {
3395 ret = -errno;
3396 }
3397 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 }
3399
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003400 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 /*
3403 * Instead of writing zeroes here, we could trust the hardware
3404 * to always provide zeroes when muted.
3405 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303406 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3407 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 memset(buffer, 0, bytes);
3409
3410exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303411 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303412 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003413 if (-ENETRESET == ret)
3414 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 pthread_mutex_unlock(&in->lock);
3417
3418 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303419 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303420 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303421 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303422 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303423 in->standby = true;
3424 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303425 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003427 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303428 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 }
3431 return bytes;
3432}
3433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003434static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435{
3436 return 0;
3437}
3438
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003439static int add_remove_audio_effect(const struct audio_stream *stream,
3440 effect_handle_t effect,
3441 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003443 struct stream_in *in = (struct stream_in *)stream;
3444 int status = 0;
3445 effect_descriptor_t desc;
3446
3447 status = (*effect)->get_descriptor(effect, &desc);
3448 if (status != 0)
3449 return status;
3450
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003451 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003452 pthread_mutex_lock(&in->dev->lock);
3453 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3454 in->enable_aec != enable &&
3455 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3456 in->enable_aec = enable;
3457 if (!in->standby)
3458 select_devices(in->dev, in->usecase);
3459 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003460 if (in->enable_ns != enable &&
3461 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3462 in->enable_ns = enable;
3463 if (!in->standby)
3464 select_devices(in->dev, in->usecase);
3465 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003466 pthread_mutex_unlock(&in->dev->lock);
3467 pthread_mutex_unlock(&in->lock);
3468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 return 0;
3470}
3471
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003472static int in_add_audio_effect(const struct audio_stream *stream,
3473 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474{
Eric Laurent994a6932013-07-17 11:51:42 -07003475 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003476 return add_remove_audio_effect(stream, effect, true);
3477}
3478
3479static int in_remove_audio_effect(const struct audio_stream *stream,
3480 effect_handle_t effect)
3481{
Eric Laurent994a6932013-07-17 11:51:42 -07003482 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003483 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484}
3485
3486static int adev_open_output_stream(struct audio_hw_device *dev,
3487 audio_io_handle_t handle,
3488 audio_devices_t devices,
3489 audio_output_flags_t flags,
3490 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003491 struct audio_stream_out **stream_out,
3492 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493{
3494 struct audio_device *adev = (struct audio_device *)dev;
3495 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303496 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003497 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303500
3501 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3502 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003503 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303504 return -EINVAL;
3505 }
3506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3508
Mingming Yin3a941d42016-02-17 18:08:05 -08003509 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3510 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303511 devices, flags, &out->stream);
3512
3513
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003514 if (!out) {
3515 return -ENOMEM;
3516 }
3517
Haynes Mathew George204045b2015-02-25 20:32:03 -08003518 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003519 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003520 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 if (devices == AUDIO_DEVICE_NONE)
3523 devices = AUDIO_DEVICE_OUT_SPEAKER;
3524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 out->flags = flags;
3526 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003527 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003528 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003529 out->sample_rate = config->sample_rate;
3530 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3531 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003532 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003533 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003534 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303535 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536
Mingming Yin3a941d42016-02-17 18:08:05 -08003537 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3538 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3539 pthread_mutex_lock(&adev->lock);
3540 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3541 ret = read_hdmi_sink_caps(out);
3542 pthread_mutex_unlock(&adev->lock);
3543 if (ret != 0) {
3544 if (ret == -ENOSYS) {
3545 /* ignore and go with default */
3546 ret = 0;
3547 } else {
3548 ALOGE("error reading hdmi sink caps");
3549 goto error_open;
3550 }
3551 }
3552 }
3553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003555 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303556 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3557 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003558 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3559 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3560
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003561 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003562 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3563 /*
3564 * Do not handle stereo output in Multi-channel cases
3565 * Stereo case is handled in normal playback path
3566 */
3567 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3568 ret = AUDIO_CHANNEL_OUT_STEREO;
3569 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003570
3571 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3572 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003573 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003574 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003575 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003576
3577 if (config->sample_rate == 0)
3578 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3579 if (config->channel_mask == 0)
3580 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003581 if (config->format == 0)
3582 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003583
3584 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003585 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003586 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3588 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003590 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3593 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003594 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003595 ret = voice_extn_compress_voip_open_output_stream(out);
3596 if (ret != 0) {
3597 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3598 __func__, ret);
3599 goto error_open;
3600 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003601 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3602 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3603
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003604 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3605 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3606 ALOGE("%s: Unsupported Offload information", __func__);
3607 ret = -EINVAL;
3608 goto error_open;
3609 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003610
Mingming Yin3a941d42016-02-17 18:08:05 -08003611 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003612 if(config->offload_info.format == 0)
3613 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003614 if (config->offload_info.sample_rate == 0)
3615 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003616 }
3617
Mingming Yin90310102013-11-13 16:57:00 -08003618 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303619 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003620 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 ret = -EINVAL;
3622 goto error_open;
3623 }
3624
3625 out->compr_config.codec = (struct snd_codec *)
3626 calloc(1, sizeof(struct snd_codec));
3627
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003628 if (!out->compr_config.codec) {
3629 ret = -ENOMEM;
3630 goto error_open;
3631 }
3632
vivek mehta0ea887a2015-08-26 14:01:20 -07003633 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303634 out->stream.pause = out_pause;
3635 out->stream.flush = out_flush;
3636 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003637 out->usecase = get_offload_usecase(adev, true);
3638 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003639 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003640 out->stream.set_callback = out_set_callback;
3641 out->stream.pause = out_pause;
3642 out->stream.resume = out_resume;
3643 out->stream.drain = out_drain;
3644 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003645 out->usecase = get_offload_usecase(adev, false);
3646 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003647 }
vivek mehta446c3962015-09-14 10:57:35 -07003648
3649 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003650 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3651 config->format == 0 && config->sample_rate == 0 &&
3652 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003653 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003654 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3655 } else {
3656 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3657 ret = -EEXIST;
3658 goto error_open;
3659 }
vivek mehta446c3962015-09-14 10:57:35 -07003660 }
3661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 if (config->offload_info.channel_mask)
3663 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003664 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003666 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003667 } else {
3668 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3669 ret = -EINVAL;
3670 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003671 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003672
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003673 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 out->sample_rate = config->offload_info.sample_rate;
3675
Mingming Yin3ee55c62014-08-04 14:23:35 -07003676 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003677
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303678 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3679 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3680 audio_extn_dolby_send_ddp_endp_params(adev);
3681 audio_extn_dolby_set_dmid(adev);
3682 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003685 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686 out->compr_config.codec->bit_rate =
3687 config->offload_info.bit_rate;
3688 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303689 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303691 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003692 /*TODO: Do we need to change it for passthrough */
3693 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003694
Manish Dewangana6fc5442015-08-24 20:30:31 +05303695 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3696 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3697 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3698 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303699
3700 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3701 AUDIO_FORMAT_PCM) {
3702
3703 /*Based on platform support, configure appropriate alsa format for corresponding
3704 *hal input format.
3705 */
3706 out->compr_config.codec->format = hal_format_to_alsa(
3707 config->offload_info.format);
3708
Ashish Jain83a6cc22016-06-28 14:34:17 +05303709 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303710 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303711 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303712
3713 /*for direct PCM playback populate bit_width based on selected alsa format as
3714 *hal input format and alsa format might differ based on platform support.
3715 */
3716 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303717 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303718
3719 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3720
3721 /* Check if alsa session is configured with the same format as HAL input format,
3722 * if not then derive correct fragment size needed to accomodate the
3723 * conversion of HAL input format to alsa format.
3724 */
3725 audio_extn_utils_update_direct_pcm_fragment_size(out);
3726
3727 /*if hal input and output fragment size is different this indicates HAL input format is
3728 *not same as the alsa format
3729 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303730 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303731 /*Allocate a buffer to convert input data to the alsa configured format.
3732 *size of convert buffer is equal to the size required to hold one fragment size
3733 *worth of pcm data, this is because flinger does not write more than fragment_size
3734 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303735 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3736 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303737 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3738 ret = -ENOMEM;
3739 goto error_open;
3740 }
3741 }
3742 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3743 out->compr_config.fragment_size =
3744 audio_extn_passthru_get_buffer_size(&config->offload_info);
3745 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3746 } else {
3747 out->compr_config.fragment_size =
3748 platform_get_compress_offload_buffer_size(&config->offload_info);
3749 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3750 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003751
Amit Shekhar6f461b12014-08-01 14:52:58 -07003752 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303753 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003754
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3756 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003757
Alexy Josephaa54c872014-12-03 02:46:47 -08003758
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003759 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303760 out->send_next_track_params = false;
3761 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003762 out->offload_state = OFFLOAD_STATE_IDLE;
3763 out->playback_started = 0;
3764
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003765 audio_extn_dts_create_state_notifier_node(out->usecase);
3766
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003767 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3768 __func__, config->offload_info.version,
3769 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303770
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303771 /*Check if DSD audio format is supported in codec
3772 *and there is no active native DSD use case
3773 */
3774
3775 if ((config->format == AUDIO_FORMAT_DSD) &&
3776 (!platform_check_codec_dsd_support(adev->platform) ||
3777 audio_is_dsd_native_stream_active(adev))) {
3778 ret = -EINVAL;
3779 goto error_open;
3780 }
3781
Ashish Jain5106d362016-05-11 19:23:33 +05303782 /* Disable gapless if any of the following is true
3783 * passthrough playback
3784 * AV playback
3785 * Direct PCM playback
3786 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303787 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303788 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303789 config->offload_info.has_video ||
3790 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3791 check_and_set_gapless_mode(adev, false);
3792 } else
3793 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003794
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303795 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003796 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3797 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303798 if (config->format == AUDIO_FORMAT_DSD) {
3799 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3800 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3801 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003802
3803 create_offload_callback_thread(out);
3804
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003805 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303806 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003807 if (ret != 0) {
3808 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3809 __func__, ret);
3810 goto error_open;
3811 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003812 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3813 if (config->sample_rate == 0)
3814 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3815 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3816 config->sample_rate != 8000) {
3817 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3818 ret = -EINVAL;
3819 goto error_open;
3820 }
3821 out->sample_rate = config->sample_rate;
3822 out->config.rate = config->sample_rate;
3823 if (config->format == AUDIO_FORMAT_DEFAULT)
3824 config->format = AUDIO_FORMAT_PCM_16_BIT;
3825 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3826 config->format = AUDIO_FORMAT_PCM_16_BIT;
3827 ret = -EINVAL;
3828 goto error_open;
3829 }
3830 out->format = config->format;
3831 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3832 out->config = pcm_config_afe_proxy_playback;
3833 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003834 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303835 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3836 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003837 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3838 out->flags);
3839 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303840 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3841 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3842 out->config = pcm_config_low_latency;
3843 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3844 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3845 out->config = pcm_config_deep_buffer;
3846 } else {
3847 /* primary path is the default path selected if no other outputs are available/suitable */
3848 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3849 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3850 }
3851 out->hal_ip_format = format = out->format;
3852 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3853 out->hal_op_format = pcm_format_to_hal(out->config.format);
3854 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3855 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003856 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303857 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3858 if (out->hal_ip_format != out->hal_op_format) {
3859 uint32_t buffer_size = out->config.period_size *
3860 format_to_bitwidth_table[out->hal_op_format] *
3861 out->config.channels;
3862 out->convert_buffer = calloc(1, buffer_size);
3863 if (out->convert_buffer == NULL){
3864 ALOGE("Allocation failed for convert buffer for size %d",
3865 out->compr_config.fragment_size);
3866 ret = -ENOMEM;
3867 goto error_open;
3868 }
3869 ALOGD("Convert buffer allocated of size %d", buffer_size);
3870 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 }
3872
Ashish Jain83a6cc22016-06-28 14:34:17 +05303873 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3874 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3875
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003876 /* TODO remove this hardcoding and check why width is zero*/
3877 if (out->bit_width == 0)
3878 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003879 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3880 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003881 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303882 out->bit_width, out->channel_mask,
3883 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003884 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3885 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3886 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003887 if(adev->primary_output == NULL)
3888 adev->primary_output = out;
3889 else {
3890 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003891 ret = -EEXIST;
3892 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003893 }
3894 }
3895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 /* Check if this usecase is already existing */
3897 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003898 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3899 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003902 ret = -EEXIST;
3903 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 }
3905 pthread_mutex_unlock(&adev->lock);
3906
3907 out->stream.common.get_sample_rate = out_get_sample_rate;
3908 out->stream.common.set_sample_rate = out_set_sample_rate;
3909 out->stream.common.get_buffer_size = out_get_buffer_size;
3910 out->stream.common.get_channels = out_get_channels;
3911 out->stream.common.get_format = out_get_format;
3912 out->stream.common.set_format = out_set_format;
3913 out->stream.common.standby = out_standby;
3914 out->stream.common.dump = out_dump;
3915 out->stream.common.set_parameters = out_set_parameters;
3916 out->stream.common.get_parameters = out_get_parameters;
3917 out->stream.common.add_audio_effect = out_add_audio_effect;
3918 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3919 out->stream.get_latency = out_get_latency;
3920 out->stream.set_volume = out_set_volume;
3921 out->stream.write = out_write;
3922 out->stream.get_render_position = out_get_render_position;
3923 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003924 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003926 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003928 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003929 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930
3931 config->format = out->stream.common.get_format(&out->stream.common);
3932 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3933 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3934
3935 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303936 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003937 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003938
3939 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3940 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3941 popcount(out->channel_mask), out->playback_started);
3942
Eric Laurent994a6932013-07-17 11:51:42 -07003943 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003945
3946error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303947 if (out->convert_buffer)
3948 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003949 free(out);
3950 *stream_out = NULL;
3951 ALOGD("%s: exit: ret %d", __func__, ret);
3952 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953}
3954
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003955static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 struct audio_stream_out *stream)
3957{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958 struct stream_out *out = (struct stream_out *)stream;
3959 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003960 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003961
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303962 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3963
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003964 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303965 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003966 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303967 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003968 if(ret != 0)
3969 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3970 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003971 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003972 out_standby(&stream->common);
3973
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003974 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003975 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003977 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978 if (out->compr_config.codec != NULL)
3979 free(out->compr_config.codec);
3980 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003981
Ashish Jain83a6cc22016-06-28 14:34:17 +05303982 if (out->convert_buffer != NULL) {
3983 free(out->convert_buffer);
3984 out->convert_buffer = NULL;
3985 }
3986
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003987 if (adev->voice_tx_output == out)
3988 adev->voice_tx_output = NULL;
3989
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003990 pthread_cond_destroy(&out->cond);
3991 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003993 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994}
3995
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003996static void close_compress_sessions(struct audio_device *adev)
3997{
Mingming Yin7b762e72015-03-04 13:47:32 -08003998 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303999 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004000 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004001 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304002
4003 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004004 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304005 if (is_offload_usecase(usecase->id)) {
4006 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004007 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4008 out = usecase->stream.out;
4009 pthread_mutex_unlock(&adev->lock);
4010 out_standby(&out->stream.common);
4011 pthread_mutex_lock(&adev->lock);
4012 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304013 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004014 }
4015 pthread_mutex_unlock(&adev->lock);
4016}
4017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4019{
4020 struct audio_device *adev = (struct audio_device *)dev;
4021 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004023 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004024 int ret;
4025 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004027 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304030 if (!parms)
4031 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004032 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4033 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304034 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304035 if (strstr(snd_card_status, "OFFLINE")) {
4036 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304037 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004038 //close compress sessions on OFFLINE status
4039 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304040 } else if (strstr(snd_card_status, "ONLINE")) {
4041 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304042 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004043 //send dts hpx license if enabled
4044 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304045 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304046 }
4047
4048 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004049 status = voice_set_parameters(adev, parms);
4050 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004051 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004053 status = platform_set_parameters(adev->platform, parms);
4054 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004055 goto done;
4056
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004057 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4058 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004059 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4061 adev->bluetooth_nrec = true;
4062 else
4063 adev->bluetooth_nrec = false;
4064 }
4065
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004066 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4067 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4069 adev->screen_off = false;
4070 else
4071 adev->screen_off = true;
4072 }
4073
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004074 ret = str_parms_get_int(parms, "rotation", &val);
4075 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004076 bool reverse_speakers = false;
4077 switch(val) {
4078 // FIXME: note that the code below assumes that the speakers are in the correct placement
4079 // relative to the user when the device is rotated 90deg from its default rotation. This
4080 // assumption is device-specific, not platform-specific like this code.
4081 case 270:
4082 reverse_speakers = true;
4083 break;
4084 case 0:
4085 case 90:
4086 case 180:
4087 break;
4088 default:
4089 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004090 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004091 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004092 if (status == 0) {
4093 if (adev->speaker_lr_swap != reverse_speakers) {
4094 adev->speaker_lr_swap = reverse_speakers;
4095 // only update the selected device if there is active pcm playback
4096 struct audio_usecase *usecase;
4097 struct listnode *node;
4098 list_for_each(node, &adev->usecase_list) {
4099 usecase = node_to_item(node, struct audio_usecase, list);
4100 if (usecase->type == PCM_PLAYBACK) {
4101 select_devices(adev, usecase->id);
4102 break;
4103 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004104 }
4105 }
4106 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004107 }
4108
Mingming Yin514a8bc2014-07-29 15:22:21 -07004109 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4110 if (ret >= 0) {
4111 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4112 adev->bt_wb_speech_enabled = true;
4113 else
4114 adev->bt_wb_speech_enabled = false;
4115 }
4116
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004117 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4118 if (ret >= 0) {
4119 val = atoi(value);
4120 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004121 ALOGV("cache new ext disp type and edid");
4122 ret = platform_get_ext_disp_type(adev->platform);
4123 if (ret < 0) {
4124 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4125 return ret;
4126 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004127 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004128 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004129 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004130 /*
4131 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4132 * Per AudioPolicyManager, USB device is higher priority than WFD.
4133 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4134 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4135 * starting voice call on USB
4136 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004137 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4138 if (ret >= 0) {
4139 audio_extn_usb_add_device(val, atoi(value));
4140 }
vivek mehta344576a2016-04-12 18:56:03 -07004141 ALOGV("detected USB connect .. disable proxy");
4142 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004143 }
4144 }
4145
4146 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4147 if (ret >= 0) {
4148 val = atoi(value);
4149 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4150 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004151 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004152 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004153 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004154 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4155 if (ret >= 0) {
4156 audio_extn_usb_remove_device(val, atoi(value));
4157 }
vivek mehta344576a2016-04-12 18:56:03 -07004158 ALOGV("detected USB disconnect .. enable proxy");
4159 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004160 }
4161 }
4162
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304163 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4164 if (ret >= 0) {
4165 struct audio_usecase *usecase;
4166 struct listnode *node;
4167 list_for_each(node, &adev->usecase_list) {
4168 usecase = node_to_item(node, struct audio_usecase, list);
4169 if ((usecase->type == PCM_PLAYBACK) &&
4170 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4171 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304172 lock_output_stream(usecase->stream.out);
4173 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304174 //force device switch to re configure encoder
4175 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304176 audio_extn_a2dp_set_handoff_mode(false);
4177 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304178 break;
4179 }
4180 }
4181 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304182 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004183done:
4184 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004185 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304186error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004187 ALOGV("%s: exit with code(%d)", __func__, status);
4188 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189}
4190
4191static char* adev_get_parameters(const struct audio_hw_device *dev,
4192 const char *keys)
4193{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004194 struct audio_device *adev = (struct audio_device *)dev;
4195 struct str_parms *reply = str_parms_create();
4196 struct str_parms *query = str_parms_create_str(keys);
4197 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304198 char value[256] = {0};
4199 int ret = 0;
4200
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004201 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004202 if (reply) {
4203 str_parms_destroy(reply);
4204 }
4205 if (query) {
4206 str_parms_destroy(query);
4207 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004208 ALOGE("adev_get_parameters: failed to create query or reply");
4209 return NULL;
4210 }
4211
Naresh Tannirud7205b62014-06-20 02:54:48 +05304212 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4213 sizeof(value));
4214 if (ret >=0) {
4215 int val = 1;
4216 pthread_mutex_lock(&adev->snd_card_status.lock);
4217 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4218 val = 0;
4219 pthread_mutex_unlock(&adev->snd_card_status.lock);
4220 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4221 goto exit;
4222 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004223
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004224 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004225 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004226 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004227 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304228 pthread_mutex_unlock(&adev->lock);
4229
Naresh Tannirud7205b62014-06-20 02:54:48 +05304230exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004231 str = str_parms_to_str(reply);
4232 str_parms_destroy(query);
4233 str_parms_destroy(reply);
4234
4235 ALOGV("%s: exit: returns - %s", __func__, str);
4236 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237}
4238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004239static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240{
4241 return 0;
4242}
4243
4244static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4245{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004246 int ret;
4247 struct audio_device *adev = (struct audio_device *)dev;
4248 pthread_mutex_lock(&adev->lock);
4249 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004250 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004251 pthread_mutex_unlock(&adev->lock);
4252 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253}
4254
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004255static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4256 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257{
4258 return -ENOSYS;
4259}
4260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004261static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4262 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263{
4264 return -ENOSYS;
4265}
4266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004267static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4268 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269{
4270 return -ENOSYS;
4271}
4272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004273static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4274 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275{
4276 return -ENOSYS;
4277}
4278
4279static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4280{
4281 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 pthread_mutex_lock(&adev->lock);
4284 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004285 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004287 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004288 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004289 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004290 adev->current_call_output = NULL;
4291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 }
4293 pthread_mutex_unlock(&adev->lock);
4294 return 0;
4295}
4296
4297static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4298{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004299 int ret;
4300
4301 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004302 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004303 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4304 pthread_mutex_unlock(&adev->lock);
4305
4306 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307}
4308
4309static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4310{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004311 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312 return 0;
4313}
4314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004315static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 const struct audio_config *config)
4317{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004318 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004320 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4321 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322}
4323
4324static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004325 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 audio_devices_t devices,
4327 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004328 struct audio_stream_in **stream_in,
4329 audio_input_flags_t flags __unused,
4330 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004331 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332{
4333 struct audio_device *adev = (struct audio_device *)dev;
4334 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004335 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004336 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004337 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304340 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4341 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344
4345 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004346
4347 if (!in) {
4348 ALOGE("failed to allocate input stream");
4349 return -ENOMEM;
4350 }
4351
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304352 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304353 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4354 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004355 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004356 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 in->stream.common.get_sample_rate = in_get_sample_rate;
4359 in->stream.common.set_sample_rate = in_set_sample_rate;
4360 in->stream.common.get_buffer_size = in_get_buffer_size;
4361 in->stream.common.get_channels = in_get_channels;
4362 in->stream.common.get_format = in_get_format;
4363 in->stream.common.set_format = in_set_format;
4364 in->stream.common.standby = in_standby;
4365 in->stream.common.dump = in_dump;
4366 in->stream.common.set_parameters = in_set_parameters;
4367 in->stream.common.get_parameters = in_get_parameters;
4368 in->stream.common.add_audio_effect = in_add_audio_effect;
4369 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4370 in->stream.set_gain = in_set_gain;
4371 in->stream.read = in_read;
4372 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4373
4374 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004375 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 in->standby = 1;
4378 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004379 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004380 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381
4382 /* Update config params with the requested sample rate and channels */
4383 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004384 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4385 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4386 is_low_latency = true;
4387#if LOW_LATENCY_CAPTURE_USE_CASE
4388 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4389#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004390 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004391 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004392
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004393 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004394 if (in->realtime) {
4395 in->config = pcm_config_audio_capture_rt;
4396 in->sample_rate = in->config.rate;
4397 in->af_period_multiplier = af_period_multiplier;
4398 } else {
4399 in->config = pcm_config_audio_capture;
4400 in->config.rate = config->sample_rate;
4401 in->sample_rate = config->sample_rate;
4402 in->af_period_multiplier = 1;
4403 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304404 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004406 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304407 if (adev->mode != AUDIO_MODE_IN_CALL) {
4408 ret = -EINVAL;
4409 goto err_open;
4410 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004411 if (config->sample_rate == 0)
4412 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4413 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4414 config->sample_rate != 8000) {
4415 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4416 ret = -EINVAL;
4417 goto err_open;
4418 }
4419 if (config->format == AUDIO_FORMAT_DEFAULT)
4420 config->format = AUDIO_FORMAT_PCM_16_BIT;
4421 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4422 config->format = AUDIO_FORMAT_PCM_16_BIT;
4423 ret = -EINVAL;
4424 goto err_open;
4425 }
4426
4427 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4428 in->config = pcm_config_afe_proxy_record;
4429 in->config.channels = channel_count;
4430 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304431 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304432 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4433 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004434 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004435 audio_extn_compr_cap_format_supported(config->format) &&
4436 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004437 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004438 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304439 /* restrict 24 bit capture for unprocessed source only
4440 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4441 */
4442 if (config->format == AUDIO_FORMAT_DEFAULT) {
4443 config->format = AUDIO_FORMAT_PCM_16_BIT;
4444 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4445 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4446 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4447 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4448 bool ret_error = false;
4449 in->bit_width = 24;
4450 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4451 from HAL is 24_packed and 8_24
4452 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4453 24_packed return error indicating supported format is 24_packed
4454 *> In case of any other source requesting 24 bit or float return error
4455 indicating format supported is 16 bit only.
4456
4457 on error flinger will retry with supported format passed
4458 */
4459 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4460 (source != AUDIO_SOURCE_CAMCORDER)) {
4461 config->format = AUDIO_FORMAT_PCM_16_BIT;
4462 if( config->sample_rate > 48000)
4463 config->sample_rate = 48000;
4464 ret_error = true;
4465 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4466 in->config.format = PCM_FORMAT_S24_3LE;
4467 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4468 in->config.format = PCM_FORMAT_S24_LE;
4469 } else {
4470 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4471 ret_error = true;
4472 }
4473
4474 if (ret_error) {
4475 ret = -EINVAL;
4476 goto err_open;
4477 }
4478 }
4479
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004480 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004481 if (!in->realtime) {
4482 in->format = config->format;
4483 frame_size = audio_stream_in_frame_size(&in->stream);
4484 buffer_size = get_input_buffer_size(config->sample_rate,
4485 config->format,
4486 channel_count,
4487 is_low_latency);
4488 in->config.period_size = buffer_size / frame_size;
4489 }
4490
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004491 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4492 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4493 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004494 (in->config.rate == 8000 || in->config.rate == 16000 ||
4495 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004496 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4497 voice_extn_compress_voip_open_input_stream(in);
4498 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004501 /* This stream could be for sound trigger lab,
4502 get sound trigger pcm if present */
4503 audio_extn_sound_trigger_check_and_get_session(in);
4504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004506 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004507 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
4509err_open:
4510 free(in);
4511 *stream_in = NULL;
4512 return ret;
4513}
4514
4515static void adev_close_input_stream(struct audio_hw_device *dev,
4516 struct audio_stream_in *stream)
4517{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004518 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004519 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004520 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304522 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004523
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304524 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004525 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304526
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004527 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304528 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004529 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304530 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004531 if (ret != 0)
4532 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4533 __func__, ret);
4534 } else
4535 in_standby(&stream->common);
4536
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004537 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004538 audio_extn_ssr_deinit();
4539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540
Mingming Yine62d7842013-10-25 16:26:03 -07004541 if(audio_extn_compr_cap_enabled() &&
4542 audio_extn_compr_cap_format_supported(in->config.format))
4543 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004544
Mingming Yinfd7607b2016-01-22 12:48:44 -08004545 if (in->is_st_session) {
4546 ALOGV("%s: sound trigger pcm stop lab", __func__);
4547 audio_extn_sound_trigger_stop_lab(in);
4548 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004549 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 return;
4551}
4552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004553static int adev_dump(const audio_hw_device_t *device __unused,
4554 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555{
4556 return 0;
4557}
4558
4559static int adev_close(hw_device_t *device)
4560{
4561 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004562
4563 if (!adev)
4564 return 0;
4565
4566 pthread_mutex_lock(&adev_init_lock);
4567
4568 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004569 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004570 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004571 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004572 audio_route_free(adev->audio_route);
4573 free(adev->snd_dev_ref_cnt);
4574 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004575 if (adev->adm_deinit)
4576 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004577 free(device);
4578 adev = NULL;
4579 }
4580 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 return 0;
4583}
4584
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004585/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4586 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4587 * just that it _might_ work.
4588 */
4589static int period_size_is_plausible_for_low_latency(int period_size)
4590{
4591 switch (period_size) {
4592 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004593 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004594 case 240:
4595 case 320:
4596 case 480:
4597 return 1;
4598 default:
4599 return 0;
4600 }
4601}
4602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603static int adev_open(const hw_module_t *module, const char *name,
4604 hw_device_t **device)
4605{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004606 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4608
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004609 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004610 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004611 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004612 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004613 ALOGD("%s: returning existing instance of adev", __func__);
4614 ALOGD("%s: exit", __func__);
4615 pthread_mutex_unlock(&adev_init_lock);
4616 return 0;
4617 }
4618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004619 adev = calloc(1, sizeof(struct audio_device));
4620
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004621 if (!adev) {
4622 pthread_mutex_unlock(&adev_init_lock);
4623 return -ENOMEM;
4624 }
4625
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004626 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4629 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4630 adev->device.common.module = (struct hw_module_t *)module;
4631 adev->device.common.close = adev_close;
4632
4633 adev->device.init_check = adev_init_check;
4634 adev->device.set_voice_volume = adev_set_voice_volume;
4635 adev->device.set_master_volume = adev_set_master_volume;
4636 adev->device.get_master_volume = adev_get_master_volume;
4637 adev->device.set_master_mute = adev_set_master_mute;
4638 adev->device.get_master_mute = adev_get_master_mute;
4639 adev->device.set_mode = adev_set_mode;
4640 adev->device.set_mic_mute = adev_set_mic_mute;
4641 adev->device.get_mic_mute = adev_get_mic_mute;
4642 adev->device.set_parameters = adev_set_parameters;
4643 adev->device.get_parameters = adev_get_parameters;
4644 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4645 adev->device.open_output_stream = adev_open_output_stream;
4646 adev->device.close_output_stream = adev_close_output_stream;
4647 adev->device.open_input_stream = adev_open_input_stream;
4648 adev->device.close_input_stream = adev_close_input_stream;
4649 adev->device.dump = adev_dump;
4650
4651 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004653 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004654 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004657 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004658 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004659 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004660 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004661 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004662 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004663 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004664 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304665 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304666 adev->perf_lock_opts[0] = 0x101;
4667 adev->perf_lock_opts[1] = 0x20E;
4668 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304669
4670 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4671 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004672 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004673 adev->platform = platform_init(adev);
4674 if (!adev->platform) {
4675 free(adev->snd_dev_ref_cnt);
4676 free(adev);
4677 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4678 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004679 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004680 return -EINVAL;
4681 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004682
Naresh Tanniru4c630392014-05-12 01:05:52 +05304683 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4684
Eric Laurentc4aef752013-09-12 17:45:53 -07004685 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4686 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4687 if (adev->visualizer_lib == NULL) {
4688 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4689 } else {
4690 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4691 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004692 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004693 "visualizer_hal_start_output");
4694 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004695 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004696 "visualizer_hal_stop_output");
4697 }
4698 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004699 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004700 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004701
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004702 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4703 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4704 if (adev->offload_effects_lib == NULL) {
4705 ALOGE("%s: DLOPEN failed for %s", __func__,
4706 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4707 } else {
4708 ALOGV("%s: DLOPEN successful for %s", __func__,
4709 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4710 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304711 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004712 "offload_effects_bundle_hal_start_output");
4713 adev->offload_effects_stop_output =
4714 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4715 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004716 adev->offload_effects_set_hpx_state =
4717 (int (*)(bool))dlsym(adev->offload_effects_lib,
4718 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304719 adev->offload_effects_get_parameters =
4720 (void (*)(struct str_parms *, struct str_parms *))
4721 dlsym(adev->offload_effects_lib,
4722 "offload_effects_bundle_get_parameters");
4723 adev->offload_effects_set_parameters =
4724 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4725 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004726 }
4727 }
4728
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004729 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4730 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4731 if (adev->adm_lib == NULL) {
4732 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4733 } else {
4734 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4735 adev->adm_init = (adm_init_t)
4736 dlsym(adev->adm_lib, "adm_init");
4737 adev->adm_deinit = (adm_deinit_t)
4738 dlsym(adev->adm_lib, "adm_deinit");
4739 adev->adm_register_input_stream = (adm_register_input_stream_t)
4740 dlsym(adev->adm_lib, "adm_register_input_stream");
4741 adev->adm_register_output_stream = (adm_register_output_stream_t)
4742 dlsym(adev->adm_lib, "adm_register_output_stream");
4743 adev->adm_deregister_stream = (adm_deregister_stream_t)
4744 dlsym(adev->adm_lib, "adm_deregister_stream");
4745 adev->adm_request_focus = (adm_request_focus_t)
4746 dlsym(adev->adm_lib, "adm_request_focus");
4747 adev->adm_abandon_focus = (adm_abandon_focus_t)
4748 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004749 adev->adm_set_config = (adm_set_config_t)
4750 dlsym(adev->adm_lib, "adm_set_config");
4751 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4752 dlsym(adev->adm_lib, "adm_request_focus_v2");
4753 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4754 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4755 adev->adm_on_routing_change = (adm_on_routing_change_t)
4756 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004757 }
4758 }
4759
Mingming Yin514a8bc2014-07-29 15:22:21 -07004760 adev->bt_wb_speech_enabled = false;
4761
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004762 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 *device = &adev->device.common;
4764
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004765 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4766 &adev->streams_output_cfg_list);
4767
Kiran Kandi910e1862013-10-29 13:29:42 -07004768 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004769
4770 char value[PROPERTY_VALUE_MAX];
4771 int trial;
4772 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4773 trial = atoi(value);
4774 if (period_size_is_plausible_for_low_latency(trial)) {
4775 pcm_config_low_latency.period_size = trial;
4776 pcm_config_low_latency.start_threshold = trial / 4;
4777 pcm_config_low_latency.avail_min = trial / 4;
4778 configured_low_latency_capture_period_size = trial;
4779 }
4780 }
4781 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4782 trial = atoi(value);
4783 if (period_size_is_plausible_for_low_latency(trial)) {
4784 configured_low_latency_capture_period_size = trial;
4785 }
4786 }
4787
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004788 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4789 af_period_multiplier = atoi(value);
4790 if (af_period_multiplier < 0)
4791 af_period_multiplier = 2;
4792 else if (af_period_multiplier > 4)
4793 af_period_multiplier = 4;
4794
4795 ALOGV("new period_multiplier = %d", af_period_multiplier);
4796 }
4797
vivek mehta446c3962015-09-14 10:57:35 -07004798 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004799 pthread_mutex_unlock(&adev_init_lock);
4800
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004801 if (adev->adm_init)
4802 adev->adm_data = adev->adm_init();
4803
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304804 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004805 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806 return 0;
4807}
4808
4809static struct hw_module_methods_t hal_module_methods = {
4810 .open = adev_open,
4811};
4812
4813struct audio_module HAL_MODULE_INFO_SYM = {
4814 .common = {
4815 .tag = HARDWARE_MODULE_TAG,
4816 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4817 .hal_api_version = HARDWARE_HAL_API_VERSION,
4818 .id = AUDIO_HARDWARE_MODULE_ID,
4819 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004820 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 .methods = &hal_module_methods,
4822 },
4823};