blob: ca5d3ad003316c47c0ab1d3e03f50ff47a9ccf4d [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
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_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
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700799 } else if (platform_split_snd_device(adev->platform,
800 snd_device,
801 &num_devices,
802 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530803 for (i = 0; i < num_devices; i++) {
804 enable_snd_device(adev, new_snd_devices[i]);
805 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800806 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700807 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530808
809 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
810 (audio_extn_a2dp_start_playback() < 0)) {
811 ALOGE(" fail to configure A2dp control path ");
812 return -EINVAL;
813 }
814
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700815 /* due to the possibility of calibration overwrite between listen
816 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700817 audio_extn_sound_trigger_update_device_status(snd_device,
818 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530819 audio_extn_listen_update_device_status(snd_device,
820 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700821 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700822 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700823 audio_extn_sound_trigger_update_device_status(snd_device,
824 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530825 audio_extn_listen_update_device_status(snd_device,
826 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700827 return -EINVAL;
828 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300829 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700830 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530831
832 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
833 !adev->native_playback_enabled &&
834 audio_is_true_native_stream_active(adev)) {
835 ALOGD("%s: %d: napb: enabling native mode in hardware",
836 __func__, __LINE__);
837 audio_route_apply_and_update_path(adev->audio_route,
838 "true-native-mode");
839 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 return 0;
843}
844
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700845int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700846 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530848 int i, num_devices = 0;
849 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700850 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
851
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800852 if (snd_device < SND_DEVICE_MIN ||
853 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800854 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800855 return -EINVAL;
856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
858 ALOGE("%s: device ref cnt is already 0", __func__);
859 return -EINVAL;
860 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700861
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700863
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700864 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
865 ALOGE("%s: Invalid sound device returned", __func__);
866 return -EINVAL;
867 }
868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700870 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530871
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800872 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
873 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700874 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700875 } else if (platform_split_snd_device(adev->platform,
876 snd_device,
877 &num_devices,
878 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530879 for (i = 0; i < num_devices; i++) {
880 disable_snd_device(adev, new_snd_devices[i]);
881 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300882 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700883 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300884 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700885
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530886 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
887 audio_extn_a2dp_stop_playback();
888
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700889 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530890 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530891 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
892 adev->native_playback_enabled) {
893 ALOGD("%s: %d: napb: disabling native mode in hardware",
894 __func__, __LINE__);
895 audio_route_reset_and_update_path(adev->audio_route,
896 "true-native-mode");
897 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530898 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
899 adev->asrc_mode_enabled) {
900 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530901 disable_asrc_mode(adev);
902 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530903 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530904
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200905 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700906 audio_extn_sound_trigger_update_device_status(snd_device,
907 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530908 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800909 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 return 0;
913}
914
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700915/*
916 legend:
917 uc - existing usecase
918 new_uc - new usecase
919 d1, d11, d2 - SND_DEVICE enums
920 a1, a2 - corresponding ANDROID device enums
921 B1, B2 - backend strings
922
923case 1
924 uc->dev d1 (a1) B1
925 new_uc->dev d1 (a1), d2 (a2) B1, B2
926
927 resolution: disable and enable uc->dev on d1
928
929case 2
930 uc->dev d1 (a1) B1
931 new_uc->dev d11 (a1) B1
932
933 resolution: need to switch uc since d1 and d11 are related
934 (e.g. speaker and voice-speaker)
935 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
936
937case 3
938 uc->dev d1 (a1) B1
939 new_uc->dev d2 (a2) B2
940
941 resolution: no need to switch uc
942
943case 4
944 uc->dev d1 (a1) B1
945 new_uc->dev d2 (a2) B1
946
947 resolution: disable enable uc-dev on d2 since backends match
948 we cannot enable two streams on two different devices if they
949 share the same backend. e.g. if offload is on speaker device using
950 QUAD_MI2S backend and a low-latency stream is started on voice-handset
951 using the same backend, offload must also be switched to voice-handset.
952
953case 5
954 uc->dev d1 (a1) B1
955 new_uc->dev d1 (a1), d2 (a2) B1
956
957 resolution: disable enable uc-dev on d2 since backends match
958 we cannot enable two streams on two different devices if they
959 share the same backend.
960
961case 6
962 uc->dev d1 (a1) B1
963 new_uc->dev d2 (a1) B2
964
965 resolution: no need to switch
966
967case 7
968 uc->dev d1 (a1), d2 (a2) B1, B2
969 new_uc->dev d1 (a1) B1
970
971 resolution: no need to switch
972
973*/
974static snd_device_t derive_playback_snd_device(void * platform,
975 struct audio_usecase *uc,
976 struct audio_usecase *new_uc,
977 snd_device_t new_snd_device)
978{
979 audio_devices_t a1 = uc->stream.out->devices;
980 audio_devices_t a2 = new_uc->stream.out->devices;
981
982 snd_device_t d1 = uc->out_snd_device;
983 snd_device_t d2 = new_snd_device;
984
985 // Treat as a special case when a1 and a2 are not disjoint
986 if ((a1 != a2) && (a1 & a2)) {
987 snd_device_t d3[2];
988 int num_devices = 0;
989 int ret = platform_split_snd_device(platform,
990 popcount(a1) > 1 ? d1 : d2,
991 &num_devices,
992 d3);
993 if (ret < 0) {
994 if (ret != -ENOSYS) {
995 ALOGW("%s failed to split snd_device %d",
996 __func__,
997 popcount(a1) > 1 ? d1 : d2);
998 }
999 goto end;
1000 }
1001
1002 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1003 // But if it does happen, we need to give priority to d2 if
1004 // the combo devices active on the existing usecase share a backend.
1005 // This is because we cannot have a usecase active on a combo device
1006 // and a new usecase requests one device in this combo pair.
1007 if (platform_check_backends_match(d3[0], d3[1])) {
1008 return d2; // case 5
1009 } else {
1010 return d1; // case 1
1011 }
1012 } else {
1013 if (platform_check_backends_match(d1, d2)) {
1014 return d2; // case 2, 4
1015 } else {
1016 return d1; // case 6, 3
1017 }
1018 }
1019
1020end:
1021 return d2; // return whatever was calculated before.
1022}
1023
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301025 struct audio_usecase *uc_info,
1026 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027{
1028 struct listnode *node;
1029 struct audio_usecase *usecase;
1030 bool switch_device[AUDIO_USECASE_MAX];
1031 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301032 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 /*
1034 * This function is to make sure that all the usecases that are active on
1035 * the hardware codec backend are always routed to any one device that is
1036 * handled by the hardware codec.
1037 * For example, if low-latency and deep-buffer usecases are currently active
1038 * on speaker and out_set_parameters(headset) is received on low-latency
1039 * output, then we have to make sure deep-buffer is also switched to headset,
1040 * because of the limitation that both the devices cannot be enabled
1041 * at the same time as they share the same backend.
1042 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001043 /*
1044 * This call is to check if we need to force routing for a particular stream
1045 * If there is a backend configuration change for the device when a
1046 * new stream starts, then ADM needs to be closed and re-opened with the new
1047 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001048 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001049 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001050 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1051 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301052 /* For a2dp device reconfigure all active sessions
1053 * with new AFE encoder format based on a2dp state
1054 */
1055 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1056 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1057 audio_extn_a2dp_is_force_device_switch()) {
1058 force_routing = true;
1059 force_restart_session = true;
1060 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301061 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001063 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001064 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001065 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1067 switch_device[i] = false;
1068
1069 list_for_each(node, &adev->usecase_list) {
1070 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001071
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301072 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1073 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301074 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301075 platform_get_snd_device_name(usecase->out_snd_device),
1076 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001077 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301078 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001079 (derive_playback_snd_device(adev->platform,
1080 usecase, uc_info,
1081 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301082 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1083 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301084 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301085 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301086 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1087
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1089 __func__, use_case_table[usecase->id],
1090 platform_get_snd_device_name(usecase->out_snd_device));
1091 disable_audio_route(adev, usecase);
1092 switch_device[usecase->id] = true;
1093 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 }
1095 }
1096
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301097 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1098 num_uc_to_switch);
1099
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001101 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301103 /* Make sure the previous devices to be disabled first and then enable the
1104 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 list_for_each(node, &adev->usecase_list) {
1106 usecase = node_to_item(node, struct audio_usecase, list);
1107 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001108 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 }
1110 }
1111
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001112 list_for_each(node, &adev->usecase_list) {
1113 usecase = node_to_item(node, struct audio_usecase, list);
1114 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001115 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001116 }
1117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 /* Re-route all the usecases on the shared backend other than the
1120 specified usecase to new snd devices */
1121 list_for_each(node, &adev->usecase_list) {
1122 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301123 /* Update the out_snd_device only before enabling the audio route */
1124 if (switch_device[usecase->id]) {
1125 usecase->out_snd_device = snd_device;
1126 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301127 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301128 use_case_table[usecase->id],
1129 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301130 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 }
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 }
1135}
1136
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301137static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001138 struct audio_usecase *uc_info,
1139 snd_device_t snd_device)
1140{
1141 struct listnode *node;
1142 struct audio_usecase *usecase;
1143 bool switch_device[AUDIO_USECASE_MAX];
1144 int i, num_uc_to_switch = 0;
1145
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301146 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1147 snd_device);
1148 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001149 /*
1150 * This function is to make sure that all the active capture usecases
1151 * are always routed to the same input sound device.
1152 * For example, if audio-record and voice-call usecases are currently
1153 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1154 * is received for voice call then we have to make sure that audio-record
1155 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1156 * because of the limitation that two devices cannot be enabled
1157 * at the same time if they share the same backend.
1158 */
1159 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1160 switch_device[i] = false;
1161
1162 list_for_each(node, &adev->usecase_list) {
1163 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001164 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301166 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001167 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301168 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001169 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001170 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001171 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1172 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001173 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001174 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175 switch_device[usecase->id] = true;
1176 num_uc_to_switch++;
1177 }
1178 }
1179
1180 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001181 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301183 /* Make sure the previous devices to be disabled first and then enable the
1184 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
1187 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001188 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001189 }
1190 }
1191
1192 list_for_each(node, &adev->usecase_list) {
1193 usecase = node_to_item(node, struct audio_usecase, list);
1194 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001195 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196 }
1197 }
1198
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001199 /* Re-route all the usecases on the shared backend other than the
1200 specified usecase to new snd devices */
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 /* Update the in_snd_device only before enabling the audio route */
1204 if (switch_device[usecase->id] ) {
1205 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001206 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301207 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001208 }
1209 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 }
1211}
1212
Mingming Yin3a941d42016-02-17 18:08:05 -08001213static void reset_hdmi_sink_caps(struct stream_out *out) {
1214 int i = 0;
1215
1216 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1217 out->supported_channel_masks[i] = 0;
1218 }
1219 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1220 out->supported_formats[i] = 0;
1221 }
1222 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1223 out->supported_sample_rates[i] = 0;
1224 }
1225}
1226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001228static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229{
Mingming Yin3a941d42016-02-17 18:08:05 -08001230 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001231 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Mingming Yin3a941d42016-02-17 18:08:05 -08001233 reset_hdmi_sink_caps(out);
1234
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001235 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001236 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001237 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001238 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001239 }
1240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001243 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001244 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001245 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1246 case 6:
1247 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1249 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1250 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1252 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 break;
1254 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001255 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001256 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 break;
1258 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001259
1260 // check channel format caps
1261 i = 0;
1262 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1263 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1264 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1265 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1266 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1267 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1268 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1269 }
1270
1271 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1272 ALOGV(":%s HDMI supports DTS format", __func__);
1273 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1274 }
1275
1276 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1277 ALOGV(":%s HDMI supports DTS HD format", __func__);
1278 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1279 }
1280
1281
1282 // check sample rate caps
1283 i = 0;
1284 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1285 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1286 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1287 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1288 }
1289 }
1290
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001291 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292}
1293
Alexy Josephb1379942016-01-29 15:49:38 -08001294audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001295 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001296{
1297 struct audio_usecase *usecase;
1298 struct listnode *node;
1299
1300 list_for_each(node, &adev->usecase_list) {
1301 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001302 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001303 ALOGV("%s: usecase id %d", __func__, usecase->id);
1304 return usecase->id;
1305 }
1306 }
1307 return USECASE_INVALID;
1308}
1309
Alexy Josephb1379942016-01-29 15:49:38 -08001310struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001311 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312{
1313 struct audio_usecase *usecase;
1314 struct listnode *node;
1315
1316 list_for_each(node, &adev->usecase_list) {
1317 usecase = node_to_item(node, struct audio_usecase, list);
1318 if (usecase->id == uc_id)
1319 return usecase;
1320 }
1321 return NULL;
1322}
1323
Dhananjay Kumard4833242016-10-06 22:09:12 +05301324struct stream_in *get_next_active_input(const struct audio_device *adev)
1325{
1326 struct audio_usecase *usecase;
1327 struct listnode *node;
1328
1329 list_for_each_reverse(node, &adev->usecase_list) {
1330 usecase = node_to_item(node, struct audio_usecase, list);
1331 if (usecase->type == PCM_CAPTURE)
1332 return usecase->stream.in;
1333 }
1334 return NULL;
1335}
1336
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301337/*
1338 * is a true native playback active
1339 */
1340bool audio_is_true_native_stream_active(struct audio_device *adev)
1341{
1342 bool active = false;
1343 int i = 0;
1344 struct listnode *node;
1345
1346 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1347 ALOGV("%s:napb: not in true mode or non hdphones device",
1348 __func__);
1349 active = false;
1350 goto exit;
1351 }
1352
1353 list_for_each(node, &adev->usecase_list) {
1354 struct audio_usecase *uc;
1355 uc = node_to_item(node, struct audio_usecase, list);
1356 struct stream_out *curr_out =
1357 (struct stream_out*) uc->stream.out;
1358
1359 if (curr_out && PCM_PLAYBACK == uc->type) {
1360 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1361 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1362 uc->id, curr_out->sample_rate,
1363 curr_out->bit_width,
1364 platform_get_snd_device_name(uc->out_snd_device));
1365
1366 if (is_offload_usecase(uc->id) &&
1367 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1368 active = true;
1369 ALOGD("%s:napb:native stream detected", __func__);
1370 }
1371 }
1372 }
1373exit:
1374 return active;
1375}
1376
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301377/*
1378 * if native DSD playback active
1379 */
1380bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1381{
1382 bool active = false;
1383 struct listnode *node = NULL;
1384 struct audio_usecase *uc = NULL;
1385 struct stream_out *curr_out = NULL;
1386
1387 list_for_each(node, &adev->usecase_list) {
1388 uc = node_to_item(node, struct audio_usecase, list);
1389 curr_out = (struct stream_out*) uc->stream.out;
1390
1391 if (curr_out && PCM_PLAYBACK == uc->type &&
1392 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1393 active = true;
1394 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301395 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301396 }
1397 }
1398 return active;
1399}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301400
1401static bool force_device_switch(struct audio_usecase *usecase)
1402{
1403 bool ret = false;
1404 bool is_it_true_mode = false;
1405
1406 if (is_offload_usecase(usecase->id) &&
1407 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001408 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1409 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1410 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301411 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1412 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1413 (!is_it_true_mode && adev->native_playback_enabled)){
1414 ret = true;
1415 ALOGD("napb: time to toggle native mode");
1416 }
1417 }
1418
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301419 // Force all a2dp output devices to reconfigure for proper AFE encode format
1420 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001421 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301422 audio_extn_a2dp_is_force_device_switch()) {
1423 ALOGD("Force a2dp device switch to update new encoder config");
1424 ret = true;
1425 }
1426
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301427 return ret;
1428}
1429
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001430int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001432 snd_device_t out_snd_device = SND_DEVICE_NONE;
1433 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 struct audio_usecase *usecase = NULL;
1435 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001436 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001437 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001438 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301441 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1442
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 usecase = get_usecase_from_list(adev, uc_id);
1444 if (usecase == NULL) {
1445 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1446 return -EINVAL;
1447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001449 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001450 (usecase->type == VOIP_CALL) ||
1451 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301452 if(usecase->stream.out == NULL) {
1453 ALOGE("%s: stream.out is NULL", __func__);
1454 return -EINVAL;
1455 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001456 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001457 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001458 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001459 usecase->devices = usecase->stream.out->devices;
1460 } else {
1461 /*
1462 * If the voice call is active, use the sound devices of voice call usecase
1463 * so that it would not result any device switch. All the usecases will
1464 * be switched to new device when select_devices() is called for voice call
1465 * usecase. This is to avoid switching devices for voice call when
1466 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001467 * choose voice call device only if the use case device is
1468 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001470 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001471 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001472 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001473 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1474 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301475 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1476 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001477 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 in_snd_device = vc_usecase->in_snd_device;
1479 out_snd_device = vc_usecase->out_snd_device;
1480 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001481 } else if (voice_extn_compress_voip_is_active(adev)) {
1482 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001483 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001484 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1485 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001486 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001487 in_snd_device = voip_usecase->in_snd_device;
1488 out_snd_device = voip_usecase->out_snd_device;
1489 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001490 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001491 hfp_ucid = audio_extn_hfp_get_usecase();
1492 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001493 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001494 in_snd_device = hfp_usecase->in_snd_device;
1495 out_snd_device = hfp_usecase->out_snd_device;
1496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 }
1498 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301499 if (usecase->stream.out == NULL) {
1500 ALOGE("%s: stream.out is NULL", __func__);
1501 return -EINVAL;
1502 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 usecase->devices = usecase->stream.out->devices;
1504 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001505 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001506 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001507 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001508 if (usecase->stream.out == adev->primary_output &&
1509 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001510 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001511 select_devices(adev, adev->active_input->usecase);
1512 }
1513 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301515 if (usecase->stream.in == NULL) {
1516 ALOGE("%s: stream.in is NULL", __func__);
1517 return -EINVAL;
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 usecase->devices = usecase->stream.in->device;
1520 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001521 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001522 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001523 if (adev->active_input &&
1524 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301525 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1526 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1527 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001528 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001529 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001530 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1531 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001533 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 }
1536 }
1537
1538 if (out_snd_device == usecase->out_snd_device &&
1539 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540
1541 if (!force_device_switch(usecase))
1542 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 }
1544
sangwoobc677242013-08-08 16:53:43 +09001545 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001546 out_snd_device, platform_get_snd_device_name(out_snd_device),
1547 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 /*
1550 * Limitation: While in call, to do a device switch we need to disable
1551 * and enable both RX and TX devices though one of them is same as current
1552 * device.
1553 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001554 if ((usecase->type == VOICE_CALL) &&
1555 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1556 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001558 }
1559
1560 if (((usecase->type == VOICE_CALL) ||
1561 (usecase->type == VOIP_CALL)) &&
1562 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1563 /* Disable sidetone only if voice/voip call already exists */
1564 if (voice_is_call_state_active(adev) ||
1565 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001566 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001567
1568 /* Disable aanc only if voice call exists */
1569 if (voice_is_call_state_active(adev))
1570 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001571 }
1572
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 /* Disable current sound devices */
1574 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001575 disable_audio_route(adev, usecase);
1576 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 }
1578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001580 disable_audio_route(adev, usecase);
1581 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001584 /* Applicable only on the targets that has external modem.
1585 * New device information should be sent to modem before enabling
1586 * the devices to reduce in-call device switch time.
1587 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001588 if ((usecase->type == VOICE_CALL) &&
1589 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1590 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001591 status = platform_switch_voice_call_enable_device_config(adev->platform,
1592 out_snd_device,
1593 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001594 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001595
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 /* Enable new sound devices */
1597 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001598 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301599 if (platform_check_codec_asrc_support(adev->platform))
1600 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001601 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 }
1603
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001604 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301605 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001606 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001607 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608
Avinash Vaish71a8b972014-07-24 15:36:33 +05301609 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001610 status = platform_switch_voice_call_device_post(adev->platform,
1611 out_snd_device,
1612 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301613 enable_audio_route_for_voice_usecases(adev, usecase);
1614 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001615
sangwoo170731f2013-06-08 15:36:36 +09001616 usecase->in_snd_device = in_snd_device;
1617 usecase->out_snd_device = out_snd_device;
1618
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301619 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1620 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301621 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001622 /* Notify device change info to effect clients registered */
1623 audio_extn_gef_notify_device_config(
1624 usecase->stream.out->devices,
1625 usecase->stream.out->channel_mask,
1626 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301627 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001629
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001630 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001631 /* Enable aanc only if voice call exists */
1632 if (voice_is_call_state_active(adev))
1633 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1634
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001635 /* Enable sidetone only if other voice/voip call already exists */
1636 if (voice_is_call_state_active(adev) ||
1637 voice_extn_compress_voip_is_started(adev))
1638 voice_set_sidetone(adev, out_snd_device, true);
1639 }
1640
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001641 /* Applicable only on the targets that has external modem.
1642 * Enable device command should be sent to modem only after
1643 * enabling voice call mixer controls
1644 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001645 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001646 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1647 out_snd_device,
1648 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301649 ALOGD("%s: done",__func__);
1650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 return status;
1652}
1653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654static int stop_input_stream(struct stream_in *in)
1655{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301656 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 struct audio_usecase *uc_info;
1658 struct audio_device *adev = in->dev;
1659
Dhananjay Kumard4833242016-10-06 22:09:12 +05301660 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Eric Laurent994a6932013-07-17 11:51:42 -07001662 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001663 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 uc_info = get_usecase_from_list(adev, in->usecase);
1665 if (uc_info == NULL) {
1666 ALOGE("%s: Could not find the usecase (%d) in the list",
1667 __func__, in->usecase);
1668 return -EINVAL;
1669 }
1670
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001671 /* Close in-call recording streams */
1672 voice_check_and_stop_incall_rec_usecase(adev, in);
1673
Eric Laurent150dbfe2013-02-27 14:31:02 -08001674 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001676
1677 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001678 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001680 list_remove(&uc_info->list);
1681 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682
Eric Laurent994a6932013-07-17 11:51:42 -07001683 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 return ret;
1685}
1686
1687int start_input_stream(struct stream_in *in)
1688{
1689 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001690 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 struct audio_usecase *uc_info;
1692 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301693 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694
Mingming Yin2664a5b2015-09-03 10:53:11 -07001695 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1696 if (get_usecase_from_list(adev, usecase) == NULL)
1697 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301698 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1699 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001700
Naresh Tanniru80659832014-06-04 18:17:56 +05301701
1702 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301703 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301704 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301705 goto error_config;
1706 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301707
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001708 /* Check if source matches incall recording usecase criteria */
1709 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1710 if (ret)
1711 goto error_config;
1712 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001713 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1714
1715 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1716 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1717 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001718 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001719 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001720
Eric Laurentb23d5282013-05-14 15:27:20 -07001721 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722 if (in->pcm_device_id < 0) {
1723 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1724 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001725 ret = -EINVAL;
1726 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728
1729 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001731
1732 if (!uc_info) {
1733 ret = -ENOMEM;
1734 goto error_config;
1735 }
1736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 uc_info->id = in->usecase;
1738 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001739 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740 uc_info->devices = in->device;
1741 uc_info->in_snd_device = SND_DEVICE_NONE;
1742 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001744 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301745 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1746 adev->perf_lock_opts,
1747 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301750 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1751 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001752
1753 unsigned int flags = PCM_IN;
1754 unsigned int pcm_open_retry_count = 0;
1755
1756 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1757 flags |= PCM_MMAP | PCM_NOIRQ;
1758 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001759 } else if (in->realtime) {
1760 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001761 }
1762
1763 while (1) {
1764 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1765 flags, &in->config);
1766 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1767 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1768 if (in->pcm != NULL) {
1769 pcm_close(in->pcm);
1770 in->pcm = NULL;
1771 }
1772 if (pcm_open_retry_count-- == 0) {
1773 ret = -EIO;
1774 goto error_open;
1775 }
1776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1777 continue;
1778 }
1779 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001781
1782 ALOGV("%s: pcm_prepare", __func__);
1783 ret = pcm_prepare(in->pcm);
1784 if (ret < 0) {
1785 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1786 pcm_close(in->pcm);
1787 in->pcm = NULL;
1788 goto error_open;
1789 }
1790
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001791 register_in_stream(in);
1792 if (in->realtime) {
1793 ret = pcm_start(in->pcm);
1794 if (ret < 0)
1795 goto error_open;
1796 }
1797
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301798 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001799 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001800
Eric Laurentc8400632013-02-14 19:04:54 -08001801 return ret;
1802
1803error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301804 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001806error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301807 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301808 /*
1809 * sleep 50ms to allow sufficient time for kernel
1810 * drivers to recover incases like SSR.
1811 */
1812 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001814
1815 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816}
1817
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001818void lock_input_stream(struct stream_in *in)
1819{
1820 pthread_mutex_lock(&in->pre_lock);
1821 pthread_mutex_lock(&in->lock);
1822 pthread_mutex_unlock(&in->pre_lock);
1823}
1824
1825void lock_output_stream(struct stream_out *out)
1826{
1827 pthread_mutex_lock(&out->pre_lock);
1828 pthread_mutex_lock(&out->lock);
1829 pthread_mutex_unlock(&out->pre_lock);
1830}
1831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832/* must be called with out->lock locked */
1833static int send_offload_cmd_l(struct stream_out* out, int command)
1834{
1835 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1836
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001837 if (!cmd) {
1838 ALOGE("failed to allocate mem for command 0x%x", command);
1839 return -ENOMEM;
1840 }
1841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842 ALOGVV("%s %d", __func__, command);
1843
1844 cmd->cmd = command;
1845 list_add_tail(&out->offload_cmd_list, &cmd->node);
1846 pthread_cond_signal(&out->offload_cond);
1847 return 0;
1848}
1849
1850/* must be called iwth out->lock locked */
1851static void stop_compressed_output_l(struct stream_out *out)
1852{
1853 out->offload_state = OFFLOAD_STATE_IDLE;
1854 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 if (out->compr != NULL) {
1857 compress_stop(out->compr);
1858 while (out->offload_thread_blocked) {
1859 pthread_cond_wait(&out->cond, &out->lock);
1860 }
1861 }
1862}
1863
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001864bool is_offload_usecase(audio_usecase_t uc_id)
1865{
1866 unsigned int i;
1867 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1868 if (uc_id == offload_usecases[i])
1869 return true;
1870 }
1871 return false;
1872}
1873
vivek mehta446c3962015-09-14 10:57:35 -07001874static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001875{
vivek mehta446c3962015-09-14 10:57:35 -07001876 audio_usecase_t ret_uc = USECASE_INVALID;
1877 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001878 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001879 if (!adev->multi_offload_enable) {
1880 if (is_direct_pcm)
1881 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1882 else
1883 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001884
vivek mehta446c3962015-09-14 10:57:35 -07001885 pthread_mutex_lock(&adev->lock);
1886 if (get_usecase_from_list(adev, ret_uc) != NULL)
1887 ret_uc = USECASE_INVALID;
1888 pthread_mutex_unlock(&adev->lock);
1889
1890 return ret_uc;
1891 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001892
1893 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001894 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1895 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1896 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1897 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001898 break;
1899 }
1900 }
vivek mehta446c3962015-09-14 10:57:35 -07001901
1902 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1903 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001904}
1905
1906static void free_offload_usecase(struct audio_device *adev,
1907 audio_usecase_t uc_id)
1908{
vivek mehta446c3962015-09-14 10:57:35 -07001909 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001910 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001911
1912 if (!adev->multi_offload_enable)
1913 return;
1914
1915 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1916 if (offload_usecases[offload_uc_index] == uc_id) {
1917 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918 break;
1919 }
1920 }
1921 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1922}
1923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924static void *offload_thread_loop(void *context)
1925{
1926 struct stream_out *out = (struct stream_out *) context;
1927 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001928 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1931 set_sched_policy(0, SP_FOREGROUND);
1932 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1933
1934 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001935 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 for (;;) {
1937 struct offload_cmd *cmd = NULL;
1938 stream_callback_event_t event;
1939 bool send_callback = false;
1940
1941 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1942 __func__, list_empty(&out->offload_cmd_list),
1943 out->offload_state);
1944 if (list_empty(&out->offload_cmd_list)) {
1945 ALOGV("%s SLEEPING", __func__);
1946 pthread_cond_wait(&out->offload_cond, &out->lock);
1947 ALOGV("%s RUNNING", __func__);
1948 continue;
1949 }
1950
1951 item = list_head(&out->offload_cmd_list);
1952 cmd = node_to_item(item, struct offload_cmd, node);
1953 list_remove(item);
1954
1955 ALOGVV("%s STATE %d CMD %d out->compr %p",
1956 __func__, out->offload_state, cmd->cmd, out->compr);
1957
1958 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1959 free(cmd);
1960 break;
1961 }
1962
1963 if (out->compr == NULL) {
1964 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001965 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 pthread_cond_signal(&out->cond);
1967 continue;
1968 }
1969 out->offload_thread_blocked = true;
1970 pthread_mutex_unlock(&out->lock);
1971 send_callback = false;
1972 switch(cmd->cmd) {
1973 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001974 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001975 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001976 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001977 send_callback = true;
1978 event = STREAM_CBK_EVENT_WRITE_READY;
1979 break;
1980 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001981 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301982 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001983 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301984 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001985 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301986 if (ret < 0)
1987 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301988 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301989 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001990 compress_drain(out->compr);
1991 else
1992 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301993 if (ret != -ENETRESET) {
1994 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301995 pthread_mutex_lock(&out->lock);
1996 out->send_new_metadata = 1;
1997 out->send_next_track_params = true;
1998 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301999 event = STREAM_CBK_EVENT_DRAIN_READY;
2000 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2001 } else
2002 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 break;
2004 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002005 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002007 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 send_callback = true;
2009 event = STREAM_CBK_EVENT_DRAIN_READY;
2010 break;
2011 default:
2012 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2013 break;
2014 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002015 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 out->offload_thread_blocked = false;
2017 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002018 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002019 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002021 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 free(cmd);
2023 }
2024
2025 pthread_cond_signal(&out->cond);
2026 while (!list_empty(&out->offload_cmd_list)) {
2027 item = list_head(&out->offload_cmd_list);
2028 list_remove(item);
2029 free(node_to_item(item, struct offload_cmd, node));
2030 }
2031 pthread_mutex_unlock(&out->lock);
2032
2033 return NULL;
2034}
2035
2036static int create_offload_callback_thread(struct stream_out *out)
2037{
2038 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2039 list_init(&out->offload_cmd_list);
2040 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2041 offload_thread_loop, out);
2042 return 0;
2043}
2044
2045static int destroy_offload_callback_thread(struct stream_out *out)
2046{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 stop_compressed_output_l(out);
2049 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2050
2051 pthread_mutex_unlock(&out->lock);
2052 pthread_join(out->offload_thread, (void **) NULL);
2053 pthread_cond_destroy(&out->offload_cond);
2054
2055 return 0;
2056}
2057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058static int stop_output_stream(struct stream_out *out)
2059{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 struct audio_usecase *uc_info;
2062 struct audio_device *adev = out->dev;
2063
Eric Laurent994a6932013-07-17 11:51:42 -07002064 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002065 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 uc_info = get_usecase_from_list(adev, out->usecase);
2067 if (uc_info == NULL) {
2068 ALOGE("%s: Could not find the usecase (%d) in the list",
2069 __func__, out->usecase);
2070 return -EINVAL;
2071 }
2072
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002073 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302074 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002075 if (adev->visualizer_stop_output != NULL)
2076 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002077
2078 audio_extn_dts_remove_state_notifier_node(out->usecase);
2079
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002080 if (adev->offload_effects_stop_output != NULL)
2081 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2082 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002083
Eric Laurent150dbfe2013-02-27 14:31:02 -08002084 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002085 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002086
2087 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002088 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002090 list_remove(&uc_info->list);
2091 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002093 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302094 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002095 ALOGV("Disable passthrough , reset mixer to pcm");
2096 /* NO_PASSTHROUGH */
2097 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002098 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002099 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2100 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002101
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302102 /* Must be called after removing the usecase from list */
2103 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302104 audio_extn_keep_alive_start();
2105
Eric Laurent994a6932013-07-17 11:51:42 -07002106 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 return ret;
2108}
2109
2110int start_output_stream(struct stream_out *out)
2111{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 struct audio_usecase *uc_info;
2114 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302115 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002117 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2118 ret = -EINVAL;
2119 goto error_config;
2120 }
2121
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302122 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2123 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2124 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302125
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302128 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302129 goto error_config;
2130 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302131
Eric Laurentb23d5282013-05-14 15:27:20 -07002132 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 if (out->pcm_device_id < 0) {
2134 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2135 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002136 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002137 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 }
2139
2140 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002141
2142 if (!uc_info) {
2143 ret = -ENOMEM;
2144 goto error_config;
2145 }
2146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 uc_info->id = out->usecase;
2148 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002149 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150 uc_info->devices = out->devices;
2151 uc_info->in_snd_device = SND_DEVICE_NONE;
2152 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002153 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302155 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2156 adev->perf_lock_opts,
2157 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302158
2159 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2160 audio_extn_keep_alive_stop();
2161 if (audio_extn_passthru_is_enabled() &&
2162 audio_extn_passthru_is_passthrough_stream(out)) {
2163 audio_extn_passthru_on_start(out);
2164 audio_extn_passthru_update_stream_configuration(adev, out);
2165 }
2166 }
2167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 select_devices(adev, out->usecase);
2169
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002170 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2171 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002172 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002173 unsigned int flags = PCM_OUT;
2174 unsigned int pcm_open_retry_count = 0;
2175 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2176 flags |= PCM_MMAP | PCM_NOIRQ;
2177 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002178 } else if (out->realtime) {
2179 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 } else
2181 flags |= PCM_MONOTONIC;
2182
2183 while (1) {
2184 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2185 flags, &out->config);
2186 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2187 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2188 if (out->pcm != NULL) {
2189 pcm_close(out->pcm);
2190 out->pcm = NULL;
2191 }
2192 if (pcm_open_retry_count-- == 0) {
2193 ret = -EIO;
2194 goto error_open;
2195 }
2196 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2197 continue;
2198 }
2199 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002201
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002202 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2203 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002204
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002205 ALOGV("%s: pcm_prepare", __func__);
2206 if (pcm_is_ready(out->pcm)) {
2207 ret = pcm_prepare(out->pcm);
2208 if (ret < 0) {
2209 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2210 pcm_close(out->pcm);
2211 out->pcm = NULL;
2212 goto error_open;
2213 }
2214 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002216 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2217 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002219 out->compr = compress_open(adev->snd_card,
2220 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 COMPRESS_IN, &out->compr_config);
2222 if (out->compr && !is_compress_ready(out->compr)) {
2223 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2224 compress_close(out->compr);
2225 out->compr = NULL;
2226 ret = -EIO;
2227 goto error_open;
2228 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302229 /* compress_open sends params of the track, so reset the flag here */
2230 out->is_compr_metadata_avail = false;
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 if (out->offload_callback)
2233 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002234
Fred Oh3f43e742015-03-04 18:42:34 -08002235 /* Since small bufs uses blocking writes, a write will be blocked
2236 for the default max poll time (20s) in the event of an SSR.
2237 Reduce the poll time to observe and deal with SSR faster.
2238 */
Ashish Jain5106d362016-05-11 19:23:33 +05302239 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002240 compress_set_max_poll_wait(out->compr, 1000);
2241 }
2242
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002243 audio_extn_dts_create_state_notifier_node(out->usecase);
2244 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2245 popcount(out->channel_mask),
2246 out->playback_started);
2247
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002248#ifdef DS1_DOLBY_DDP_ENABLED
2249 if (audio_extn_is_dolby_format(out->format))
2250 audio_extn_dolby_send_ddp_endp_params(adev);
2251#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302252 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002253 if (adev->visualizer_start_output != NULL)
2254 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2255 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302256 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002257 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002260
2261 if (ret == 0) {
2262 register_out_stream(out);
2263 if (out->realtime) {
2264 ret = pcm_start(out->pcm);
2265 if (ret < 0)
2266 goto error_open;
2267 }
2268 }
2269
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302270 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002271 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002272
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002273 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302275 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002277error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302278 /*
2279 * sleep 50ms to allow sufficient time for kernel
2280 * drivers to recover incases like SSR.
2281 */
2282 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284}
2285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286static int check_input_parameters(uint32_t sample_rate,
2287 audio_format_t format,
2288 int channel_count)
2289{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002290 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302292 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2293 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2294 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002295 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302296 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002297
2298 switch (channel_count) {
2299 case 1:
2300 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302301 case 3:
2302 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002303 case 6:
2304 break;
2305 default:
2306 ret = -EINVAL;
2307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308
2309 switch (sample_rate) {
2310 case 8000:
2311 case 11025:
2312 case 12000:
2313 case 16000:
2314 case 22050:
2315 case 24000:
2316 case 32000:
2317 case 44100:
2318 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302319 case 96000:
2320 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 break;
2322 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002323 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 }
2325
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002326 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327}
2328
2329static size_t get_input_buffer_size(uint32_t sample_rate,
2330 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002331 int channel_count,
2332 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 size_t size = 0;
2335
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002336 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2337 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002339 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002340 if (is_low_latency)
2341 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302342
2343 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002345 /* make sure the size is multiple of 32 bytes
2346 * At 48 kHz mono 16-bit PCM:
2347 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2348 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2349 */
2350 size += 0x1f;
2351 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002352
2353 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354}
2355
Ashish Jain058165c2016-09-28 23:18:48 +05302356static size_t get_output_period_size(uint32_t sample_rate,
2357 audio_format_t format,
2358 int channel_count,
2359 int duration /*in millisecs*/)
2360{
2361 size_t size = 0;
2362 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2363
2364 if ((duration == 0) || (sample_rate == 0) ||
2365 (bytes_per_sample == 0) || (channel_count == 0)) {
2366 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2367 bytes_per_sample, channel_count);
2368 return -EINVAL;
2369 }
2370
2371 size = (sample_rate *
2372 duration *
2373 bytes_per_sample *
2374 channel_count) / 1000;
2375 /*
2376 * To have same PCM samples for all channels, the buffer size requires to
2377 * be multiple of (number of channels * bytes per sample)
2378 * For writes to succeed, the buffer must be written at address which is multiple of 32
2379 */
2380 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2381
2382 return (size/(channel_count * bytes_per_sample));
2383}
2384
Ashish Jain5106d362016-05-11 19:23:33 +05302385static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2386{
2387 uint64_t actual_frames_rendered = 0;
2388 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2389
2390 /* This adjustment accounts for buffering after app processor.
2391 * It is based on estimated DSP latency per use case, rather than exact.
2392 */
2393 int64_t platform_latency = platform_render_latency(out->usecase) *
2394 out->sample_rate / 1000000LL;
2395
2396 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2397 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2398 * hence only estimate.
2399 */
2400 int64_t signed_frames = out->written - kernel_buffer_size;
2401
2402 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2403
2404 if (signed_frames > 0)
2405 actual_frames_rendered = signed_frames;
2406
2407 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2408 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2409 (long long int)out->written, (int)kernel_buffer_size,
2410 audio_bytes_per_sample(out->compr_config.codec->format),
2411 popcount(out->channel_mask));
2412
2413 return actual_frames_rendered;
2414}
2415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2417{
2418 struct stream_out *out = (struct stream_out *)stream;
2419
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421}
2422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002423static int out_set_sample_rate(struct audio_stream *stream __unused,
2424 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
2426 return -ENOSYS;
2427}
2428
2429static size_t out_get_buffer_size(const struct audio_stream *stream)
2430{
2431 struct stream_out *out = (struct stream_out *)stream;
2432
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002433 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002435 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2436 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302437 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302438 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002440 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002441 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442}
2443
2444static uint32_t out_get_channels(const struct audio_stream *stream)
2445{
2446 struct stream_out *out = (struct stream_out *)stream;
2447
2448 return out->channel_mask;
2449}
2450
2451static audio_format_t out_get_format(const struct audio_stream *stream)
2452{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 struct stream_out *out = (struct stream_out *)stream;
2454
2455 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002458static int out_set_format(struct audio_stream *stream __unused,
2459 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460{
2461 return -ENOSYS;
2462}
2463
2464static int out_standby(struct audio_stream *stream)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302469 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2470 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002472 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002474 if (adev->adm_deregister_stream)
2475 adev->adm_deregister_stream(adev->adm_data, out->handle);
2476
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002477 if (is_offload_usecase(out->usecase))
2478 stop_compressed_output_l(out);
2479
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002480 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002482 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2483 voice_extn_compress_voip_close_output_stream(stream);
2484 pthread_mutex_unlock(&adev->lock);
2485 pthread_mutex_unlock(&out->lock);
2486 ALOGD("VOIP output entered standby");
2487 return 0;
2488 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 if (out->pcm) {
2490 pcm_close(out->pcm);
2491 out->pcm = NULL;
2492 }
2493 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002494 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302495 out->send_next_track_params = false;
2496 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002497 out->gapless_mdata.encoder_delay = 0;
2498 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 if (out->compr != NULL) {
2500 compress_close(out->compr);
2501 out->compr = NULL;
2502 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002505 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
2507 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302508 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 return 0;
2510}
2511
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002512static int out_dump(const struct audio_stream *stream __unused,
2513 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514{
2515 return 0;
2516}
2517
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2519{
2520 int ret = 0;
2521 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002522
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002523 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002524 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002525 return -EINVAL;
2526 }
2527
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302528 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002529
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002530 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2531 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302532 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002533 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2535 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302536 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002537 }
2538
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002539 ALOGV("%s new encoder delay %u and padding %u", __func__,
2540 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2541
2542 return 0;
2543}
2544
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002545static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2546{
2547 return out == adev->primary_output || out == adev->voice_tx_output;
2548}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2551{
2552 struct stream_out *out = (struct stream_out *)stream;
2553 struct audio_device *adev = out->dev;
2554 struct str_parms *parms;
2555 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002556 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
sangwoobc677242013-08-08 16:53:43 +09002558 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002559 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302561 if (!parms)
2562 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002563 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2564 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002566 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002567 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002570 * When HDMI cable is unplugged the music playback is paused and
2571 * the policy manager sends routing=0. But the audioflinger continues
2572 * to write data until standby time (3sec). As the HDMI core is
2573 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 * Avoid this by routing audio to speaker until standby.
2575 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002576 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2577 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302578 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002579 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2580 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002581 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302582 /*
2583 * When A2DP is disconnected the
2584 * music playback is paused and the policy manager sends routing=0
2585 * But the audioflingercontinues to write data until standby time
2586 * (3sec). As BT is turned off, the write gets blocked.
2587 * Avoid this by routing audio to speaker until standby.
2588 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002589 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302590 (val == AUDIO_DEVICE_NONE)) {
2591 val = AUDIO_DEVICE_OUT_SPEAKER;
2592 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302593 /* To avoid a2dp to sco overlapping force route BT usecases
2594 * to speaker based on Phone state
2595 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002596 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302597 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2598 (adev->mode == AUDIO_MODE_IN_CALL))) {
2599 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2600 val = AUDIO_DEVICE_OUT_SPEAKER;
2601 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002602 /*
2603 * select_devices() call below switches all the usecases on the same
2604 * backend to the new device. Refer to check_usecases_codec_backend() in
2605 * the select_devices(). But how do we undo this?
2606 *
2607 * For example, music playback is active on headset (deep-buffer usecase)
2608 * and if we go to ringtones and select a ringtone, low-latency usecase
2609 * will be started on headset+speaker. As we can't enable headset+speaker
2610 * and headset devices at the same time, select_devices() switches the music
2611 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2612 * So when the ringtone playback is completed, how do we undo the same?
2613 *
2614 * We are relying on the out_set_parameters() call on deep-buffer output,
2615 * once the ringtone playback is ended.
2616 * NOTE: We should not check if the current devices are same as new devices.
2617 * Because select_devices() must be called to switch back the music
2618 * playback to headset.
2619 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002620 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002621 audio_devices_t new_dev = val;
2622 bool same_dev = out->devices == new_dev;
2623 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002624
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002625 if (output_drives_call(adev, out)) {
2626 if(!voice_is_in_call(adev)) {
2627 if (adev->mode == AUDIO_MODE_IN_CALL) {
2628 adev->current_call_output = out;
2629 ret = voice_start_call(adev);
2630 }
2631 } else {
2632 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002633 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002634 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002635 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002636
2637 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002638 if (!same_dev) {
2639 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302640 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2641 adev->perf_lock_opts,
2642 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002643 if (adev->adm_on_routing_change)
2644 adev->adm_on_routing_change(adev->adm_data,
2645 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002646 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002647 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302648 if (!same_dev)
2649 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002650 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002651 }
2652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002654 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002656
2657 if (out == adev->primary_output) {
2658 pthread_mutex_lock(&adev->lock);
2659 audio_extn_set_parameters(adev, parms);
2660 pthread_mutex_unlock(&adev->lock);
2661 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002662 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002663 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002664 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002665
2666 audio_extn_dts_create_state_notifier_node(out->usecase);
2667 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2668 popcount(out->channel_mask),
2669 out->playback_started);
2670
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002671 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002672 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002673
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302674 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2675 if (err >= 0) {
2676 strlcpy(out->profile, value, sizeof(out->profile));
2677 ALOGV("updating stream profile with value '%s'", out->profile);
2678 lock_output_stream(out);
2679 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2680 &adev->streams_output_cfg_list,
2681 out->devices, out->flags, out->format,
2682 out->sample_rate, out->bit_width,
2683 out->channel_mask, out->profile,
2684 &out->app_type_cfg);
2685 pthread_mutex_unlock(&out->lock);
2686 }
2687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302689error:
Eric Laurent994a6932013-07-17 11:51:42 -07002690 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 return ret;
2692}
2693
2694static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2695{
2696 struct stream_out *out = (struct stream_out *)stream;
2697 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002698 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 char value[256];
2700 struct str_parms *reply = str_parms_create();
2701 size_t i, j;
2702 int ret;
2703 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002704
2705 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002706 if (reply) {
2707 str_parms_destroy(reply);
2708 }
2709 if (query) {
2710 str_parms_destroy(query);
2711 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002712 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2713 return NULL;
2714 }
2715
Eric Laurent994a6932013-07-17 11:51:42 -07002716 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2718 if (ret >= 0) {
2719 value[0] = '\0';
2720 i = 0;
2721 while (out->supported_channel_masks[i] != 0) {
2722 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2723 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2724 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002725 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002727 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 first = false;
2729 break;
2730 }
2731 }
2732 i++;
2733 }
2734 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2735 str = str_parms_to_str(reply);
2736 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002737 voice_extn_out_get_parameters(out, query, reply);
2738 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002739 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002740 free(str);
2741 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002744
Alexy Joseph62142aa2015-11-16 15:10:34 -08002745
2746 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2747 if (ret >= 0) {
2748 value[0] = '\0';
2749 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2750 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302751 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002752 } else {
2753 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302754 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002755 }
2756 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002757 if (str)
2758 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002759 str = str_parms_to_str(reply);
2760 }
2761
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002762 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2763 if (ret >= 0) {
2764 value[0] = '\0';
2765 i = 0;
2766 first = true;
2767 while (out->supported_formats[i] != 0) {
2768 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2769 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2770 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002771 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002772 }
2773 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2774 first = false;
2775 break;
2776 }
2777 }
2778 i++;
2779 }
2780 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002781 if (str)
2782 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002783 str = str_parms_to_str(reply);
2784 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002785
2786 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2787 if (ret >= 0) {
2788 value[0] = '\0';
2789 i = 0;
2790 first = true;
2791 while (out->supported_sample_rates[i] != 0) {
2792 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2793 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2794 if (!first) {
2795 strlcat(value, "|", sizeof(value));
2796 }
2797 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2798 first = false;
2799 break;
2800 }
2801 }
2802 i++;
2803 }
2804 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2805 if (str)
2806 free(str);
2807 str = str_parms_to_str(reply);
2808 }
2809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 str_parms_destroy(query);
2811 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002812 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 return str;
2814}
2815
2816static uint32_t out_get_latency(const struct audio_stream_out *stream)
2817{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002818 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002820 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821
Alexy Josephaa54c872014-12-03 02:46:47 -08002822 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002823 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002824 } else if (out->realtime) {
2825 // since the buffer won't be filled up faster than realtime,
2826 // return a smaller number
2827 if (out->config.rate)
2828 period_ms = (out->af_period_multiplier * out->config.period_size *
2829 1000) / (out->config.rate);
2830 else
2831 period_ms = 0;
2832 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002833 } else {
2834 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002836 }
2837
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302838 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002839 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840}
2841
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302842static float AmpToDb(float amplification)
2843{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302844 float db = DSD_VOLUME_MIN_DB;
2845 if (amplification > 0) {
2846 db = 20 * log10(amplification);
2847 if(db < DSD_VOLUME_MIN_DB)
2848 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302849 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302850 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302851}
2852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853static int out_set_volume(struct audio_stream_out *stream, float left,
2854 float right)
2855{
Eric Laurenta9024de2013-04-04 09:19:12 -07002856 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002857 int volume[2];
2858
Eric Laurenta9024de2013-04-04 09:19:12 -07002859 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2860 /* only take left channel into account: the API is for stereo anyway */
2861 out->muted = (left == 0.0f);
2862 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002863 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302864 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002865 /*
2866 * Set mute or umute on HDMI passthrough stream.
2867 * Only take left channel into account.
2868 * Mute is 0 and unmute 1
2869 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302870 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302871 } else if (out->format == AUDIO_FORMAT_DSD){
2872 char mixer_ctl_name[128] = "DSD Volume";
2873 struct audio_device *adev = out->dev;
2874 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2875
2876 if (!ctl) {
2877 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2878 __func__, mixer_ctl_name);
2879 return -EINVAL;
2880 }
2881 volume[0] = (int)(AmpToDb(left));
2882 volume[1] = (int)(AmpToDb(right));
2883 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2884 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002885 } else {
2886 char mixer_ctl_name[128];
2887 struct audio_device *adev = out->dev;
2888 struct mixer_ctl *ctl;
2889 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002890 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002892 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2893 "Compress Playback %d Volume", pcm_device_id);
2894 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2895 if (!ctl) {
2896 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2897 __func__, mixer_ctl_name);
2898 return -EINVAL;
2899 }
2900 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2901 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2902 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2903 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002905 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 return -ENOSYS;
2908}
2909
2910static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2911 size_t bytes)
2912{
2913 struct stream_out *out = (struct stream_out *)stream;
2914 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302915 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002916 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002918 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302919
Naresh Tanniru80659832014-06-04 18:17:56 +05302920 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002921
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302922 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302923 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302924 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2925 pthread_mutex_unlock(&out->lock);
2926 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302927 } else {
2928 /* increase written size during SSR to avoid mismatch
2929 * with the written frames count in AF
2930 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002931 // bytes per frame
2932 size_t bpf = audio_bytes_per_sample(out->format) *
2933 audio_channel_count_from_out_mask(out->channel_mask);
2934 if (bpf != 0)
2935 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302936 ALOGD(" %s: sound card is not active/SSR state", __func__);
2937 ret= -EIO;
2938 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302939 }
2940 }
2941
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302942 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302943 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2944 if (audio_bytes_per_sample(out->format) != 0)
2945 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2946 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302947 goto exit;
2948 }
2949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002951 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002952 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002953 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2954 ret = voice_extn_compress_voip_start_output_stream(out);
2955 else
2956 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002957 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002960 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 goto exit;
2962 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002963
2964 if (last_known_cal_step != -1) {
2965 ALOGD("%s: retry previous failed cal level set", __func__);
2966 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969
Ashish Jain81eb2a82015-05-13 10:52:34 +05302970 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002971 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302972 adev->is_channel_status_set = true;
2973 }
2974
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002975 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002976 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002977 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002978 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002979 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2980 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302981 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2982 ALOGD("copl(%p):send next track params in gapless", out);
2983 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2984 out->send_next_track_params = false;
2985 out->is_compr_metadata_avail = false;
2986 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002987 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302988 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302989 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002990
Ashish Jain83a6cc22016-06-28 14:34:17 +05302991 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302992 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302993 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302994 pthread_mutex_unlock(&out->lock);
2995 return -EINVAL;
2996 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302997 audio_format_t dst_format = out->hal_op_format;
2998 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302999
3000 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3001 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3002
Ashish Jain83a6cc22016-06-28 14:34:17 +05303003 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303004 dst_format,
3005 buffer,
3006 src_format,
3007 frames);
3008
Ashish Jain83a6cc22016-06-28 14:34:17 +05303009 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303010 bytes_to_write);
3011
3012 /*Convert written bytes in audio flinger format*/
3013 if (ret > 0)
3014 ret = ((ret * format_to_bitwidth_table[out->format]) /
3015 format_to_bitwidth_table[dst_format]);
3016 }
3017 } else
3018 ret = compress_write(out->compr, buffer, bytes);
3019
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303020 if (ret < 0)
3021 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303022 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303023 /*msg to cb thread only if non blocking write is enabled*/
3024 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303025 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303027 } else if (-ENETRESET == ret) {
3028 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3029 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3030 pthread_mutex_unlock(&out->lock);
3031 out_standby(&out->stream.common);
3032 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 }
Ashish Jain5106d362016-05-11 19:23:33 +05303034 if ( ret == (ssize_t)bytes && !out->non_blocking)
3035 out->written += bytes;
3036
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303037 /* Call compr start only when non-zero bytes of data is there to be rendered */
3038 if (!out->playback_started && ret > 0) {
3039 int status = compress_start(out->compr);
3040 if (status < 0) {
3041 ret = status;
3042 ALOGE("%s: compr start failed with err %d", __func__, errno);
3043 goto exit;
3044 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003045 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 out->playback_started = 1;
3047 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003048
3049 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3050 popcount(out->channel_mask),
3051 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003052 }
3053 pthread_mutex_unlock(&out->lock);
3054 return ret;
3055 } else {
3056 if (out->pcm) {
3057 if (out->muted)
3058 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003059
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303060 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003061
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003062 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003063
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003064 if (out->config.rate)
3065 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3066 out->config.rate;
3067
3068 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3069
3070 request_out_focus(out, ns);
3071
3072 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003073 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003074 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303075 out->convert_buffer != NULL) {
3076
3077 memcpy_by_audio_format(out->convert_buffer,
3078 out->hal_op_format,
3079 buffer,
3080 out->hal_ip_format,
3081 out->config.period_size * out->config.channels);
3082
3083 ret = pcm_write(out->pcm, out->convert_buffer,
3084 (out->config.period_size *
3085 out->config.channels *
3086 format_to_bitwidth_table[out->hal_op_format]));
3087 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003088 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303089 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003090
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003091 release_out_focus(out);
3092
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303093 if (ret < 0)
3094 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303095 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3096 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3097 else
3098 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 }
3101
3102exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303103 /* ToDo: There may be a corner case when SSR happens back to back during
3104 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303105 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303106 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303107 }
3108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 pthread_mutex_unlock(&out->lock);
3110
3111 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003112 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003113 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303114 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303115 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303116 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303117 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303118 out->standby = true;
3119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303121 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3122 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3123 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 }
3125 return bytes;
3126}
3127
3128static int out_get_render_position(const struct audio_stream_out *stream,
3129 uint32_t *dsp_frames)
3130{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003131 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303132 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003133
3134 if (dsp_frames == NULL)
3135 return -EINVAL;
3136
3137 *dsp_frames = 0;
3138 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003139 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303140
3141 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3142 * this operation and adev_close_output_stream(where out gets reset).
3143 */
3144 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3145 *dsp_frames = get_actual_pcm_frames_rendered(out);
3146 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3147 return 0;
3148 }
3149
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003150 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303151 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303152 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303154 if (ret < 0)
3155 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303157 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158 }
3159 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303160 if (-ENETRESET == ret) {
3161 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3162 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3163 return -EINVAL;
3164 } else if(ret < 0) {
3165 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3166 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303167 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3168 /*
3169 * Handle corner case where compress session is closed during SSR
3170 * and timestamp is queried
3171 */
3172 ALOGE(" ERROR: sound card not active, return error");
3173 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303174 } else {
3175 return 0;
3176 }
Zhou Song32a556e2015-05-05 10:46:56 +08003177 } else if (audio_is_linear_pcm(out->format)) {
3178 *dsp_frames = out->written;
3179 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 } else
3181 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182}
3183
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003184static int out_add_audio_effect(const struct audio_stream *stream __unused,
3185 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186{
3187 return 0;
3188}
3189
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003190static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3191 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192{
3193 return 0;
3194}
3195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003196static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3197 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198{
3199 return -EINVAL;
3200}
3201
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003202static int out_get_presentation_position(const struct audio_stream_out *stream,
3203 uint64_t *frames, struct timespec *timestamp)
3204{
3205 struct stream_out *out = (struct stream_out *)stream;
3206 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003207 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003208
Ashish Jain5106d362016-05-11 19:23:33 +05303209 /* below piece of code is not guarded against any lock because audioFliner serializes
3210 * this operation and adev_close_output_stream( where out gets reset).
3211 */
3212 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3213 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3214 *frames = get_actual_pcm_frames_rendered(out);
3215 /* this is the best we can do */
3216 clock_gettime(CLOCK_MONOTONIC, timestamp);
3217 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3218 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3219 return 0;
3220 }
3221
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003222 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003223
Ashish Jain5106d362016-05-11 19:23:33 +05303224 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3225 ret = compress_get_tstamp(out->compr, &dsp_frames,
3226 &out->sample_rate);
3227 ALOGVV("%s rendered frames %ld sample_rate %d",
3228 __func__, dsp_frames, out->sample_rate);
3229 *frames = dsp_frames;
3230 if (ret < 0)
3231 ret = -errno;
3232 if (-ENETRESET == ret) {
3233 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3234 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3235 ret = -EINVAL;
3236 } else
3237 ret = 0;
3238 /* this is the best we can do */
3239 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003240 } else {
3241 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003242 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003243 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3244 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003245 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003246 // This adjustment accounts for buffering after app processor.
3247 // It is based on estimated DSP latency per use case, rather than exact.
3248 signed_frames -=
3249 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3250
Eric Laurent949a0892013-09-20 09:20:13 -07003251 // It would be unusual for this value to be negative, but check just in case ...
3252 if (signed_frames >= 0) {
3253 *frames = signed_frames;
3254 ret = 0;
3255 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003256 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303257 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3258 *frames = out->written;
3259 clock_gettime(CLOCK_MONOTONIC, timestamp);
3260 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003261 }
3262 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003263 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003264 return ret;
3265}
3266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267static int out_set_callback(struct audio_stream_out *stream,
3268 stream_callback_t callback, void *cookie)
3269{
3270 struct stream_out *out = (struct stream_out *)stream;
3271
3272 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003273 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 out->offload_callback = callback;
3275 out->offload_cookie = cookie;
3276 pthread_mutex_unlock(&out->lock);
3277 return 0;
3278}
3279
3280static int out_pause(struct audio_stream_out* stream)
3281{
3282 struct stream_out *out = (struct stream_out *)stream;
3283 int status = -ENOSYS;
3284 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003285 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003286 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003287 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303289 struct audio_device *adev = out->dev;
3290 int snd_scard_state = get_snd_card_state(adev);
3291
3292 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3293 status = compress_pause(out->compr);
3294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003296
Mingming Yin21854652016-04-13 11:54:02 -07003297 if (audio_extn_passthru_is_active()) {
3298 ALOGV("offload use case, pause passthru");
3299 audio_extn_passthru_on_pause(out);
3300 }
3301
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303302 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003303 audio_extn_dts_notify_playback_state(out->usecase, 0,
3304 out->sample_rate, popcount(out->channel_mask),
3305 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306 }
3307 pthread_mutex_unlock(&out->lock);
3308 }
3309 return status;
3310}
3311
3312static int out_resume(struct audio_stream_out* stream)
3313{
3314 struct stream_out *out = (struct stream_out *)stream;
3315 int status = -ENOSYS;
3316 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003317 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003318 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003319 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003320 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303322 struct audio_device *adev = out->dev;
3323 int snd_scard_state = get_snd_card_state(adev);
3324
Mingming Yin21854652016-04-13 11:54:02 -07003325 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3326 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3327 pthread_mutex_lock(&out->dev->lock);
3328 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003329 pthread_mutex_unlock(&out->dev->lock);
3330 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303331 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003332 }
3333 if (!status) {
3334 out->offload_state = OFFLOAD_STATE_PLAYING;
3335 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303336 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003337 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3338 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339 }
3340 pthread_mutex_unlock(&out->lock);
3341 }
3342 return status;
3343}
3344
3345static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3346{
3347 struct stream_out *out = (struct stream_out *)stream;
3348 int status = -ENOSYS;
3349 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003350 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003351 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003352 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3353 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3354 else
3355 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3356 pthread_mutex_unlock(&out->lock);
3357 }
3358 return status;
3359}
3360
3361static int out_flush(struct audio_stream_out* stream)
3362{
3363 struct stream_out *out = (struct stream_out *)stream;
3364 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003365 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003366 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003367 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003368 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3369 stop_compressed_output_l(out);
3370 out->written = 0;
3371 } else {
3372 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3373 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003375 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 return 0;
3377 }
3378 return -ENOSYS;
3379}
3380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381/** audio_stream_in implementation **/
3382static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3383{
3384 struct stream_in *in = (struct stream_in *)stream;
3385
3386 return in->config.rate;
3387}
3388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389static int in_set_sample_rate(struct audio_stream *stream __unused,
3390 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 return -ENOSYS;
3393}
3394
3395static size_t in_get_buffer_size(const struct audio_stream *stream)
3396{
3397 struct stream_in *in = (struct stream_in *)stream;
3398
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003399 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3400 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003401 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3402 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003403
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003404 return in->config.period_size * in->af_period_multiplier *
3405 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406}
3407
3408static uint32_t in_get_channels(const struct audio_stream *stream)
3409{
3410 struct stream_in *in = (struct stream_in *)stream;
3411
3412 return in->channel_mask;
3413}
3414
3415static audio_format_t in_get_format(const struct audio_stream *stream)
3416{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003417 struct stream_in *in = (struct stream_in *)stream;
3418
3419 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420}
3421
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003422static int in_set_format(struct audio_stream *stream __unused,
3423 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424{
3425 return -ENOSYS;
3426}
3427
3428static int in_standby(struct audio_stream *stream)
3429{
3430 struct stream_in *in = (struct stream_in *)stream;
3431 struct audio_device *adev = in->dev;
3432 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303433 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3434 stream, in->usecase, use_case_table[in->usecase]);
3435
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003436 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003437 if (!in->standby && in->is_st_session) {
3438 ALOGD("%s: sound trigger pcm stop lab", __func__);
3439 audio_extn_sound_trigger_stop_lab(in);
3440 in->standby = 1;
3441 }
3442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003444 if (adev->adm_deregister_stream)
3445 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3446
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003447 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003449 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3450 voice_extn_compress_voip_close_input_stream(stream);
3451 ALOGD("VOIP input entered standby");
3452 } else {
3453 if (in->pcm) {
3454 pcm_close(in->pcm);
3455 in->pcm = NULL;
3456 }
3457 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003458 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003459 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 }
3461 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003462 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 return status;
3464}
3465
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003466static int in_dump(const struct audio_stream *stream __unused,
3467 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468{
3469 return 0;
3470}
3471
3472static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3473{
3474 struct stream_in *in = (struct stream_in *)stream;
3475 struct audio_device *adev = in->dev;
3476 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003478 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303480 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 parms = str_parms_create_str(kvpairs);
3482
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303483 if (!parms)
3484 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003485 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003486 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003487
3488 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3489 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 val = atoi(value);
3491 /* no audio source uses val == 0 */
3492 if ((in->source != val) && (val != 0)) {
3493 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003494 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3495 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3496 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003497 (in->config.rate == 8000 || in->config.rate == 16000 ||
3498 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003499 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003500 err = voice_extn_compress_voip_open_input_stream(in);
3501 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003502 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003503 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003504 }
3505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 }
3507 }
3508
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003509 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3510 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003512 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 in->device = val;
3514 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003515 if (!in->standby && !in->is_st_session) {
3516 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003517 if (adev->adm_on_routing_change)
3518 adev->adm_on_routing_change(adev->adm_data,
3519 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003520 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 }
3523 }
3524
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303525 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3526 if (err >= 0) {
3527 strlcpy(in->profile, value, sizeof(in->profile));
3528 ALOGV("updating stream profile with value '%s'", in->profile);
3529 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3530 &adev->streams_input_cfg_list,
3531 in->device, in->flags, in->format,
3532 in->sample_rate, in->bit_width,
3533 in->profile, &in->app_type_cfg);
3534 }
3535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003537 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
3539 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303540error:
Eric Laurent994a6932013-07-17 11:51:42 -07003541 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 return ret;
3543}
3544
3545static char* in_get_parameters(const struct audio_stream *stream,
3546 const char *keys)
3547{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003548 struct stream_in *in = (struct stream_in *)stream;
3549 struct str_parms *query = str_parms_create_str(keys);
3550 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003551 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003552
3553 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003554 if (reply) {
3555 str_parms_destroy(reply);
3556 }
3557 if (query) {
3558 str_parms_destroy(query);
3559 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003560 ALOGE("in_get_parameters: failed to create query or reply");
3561 return NULL;
3562 }
3563
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003564 ALOGV("%s: enter: keys - %s", __func__, keys);
3565
3566 voice_extn_in_get_parameters(in, query, reply);
3567
3568 str = str_parms_to_str(reply);
3569 str_parms_destroy(query);
3570 str_parms_destroy(reply);
3571
3572 ALOGV("%s: exit: returns - %s", __func__, str);
3573 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574}
3575
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003576static int in_set_gain(struct audio_stream_in *stream __unused,
3577 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578{
3579 return 0;
3580}
3581
3582static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3583 size_t bytes)
3584{
3585 struct stream_in *in = (struct stream_in *)stream;
3586 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303587 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303588 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303589 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003591 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303592
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003593 if (in->is_st_session) {
3594 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3595 /* Read from sound trigger HAL */
3596 audio_extn_sound_trigger_read(in, buffer, bytes);
3597 pthread_mutex_unlock(&in->lock);
3598 return bytes;
3599 }
3600
Ashish Jainbbce4322016-02-16 13:25:27 +05303601 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003602 ALOGD(" %s: sound card is not active/SSR state", __func__);
3603 ret= -EIO;;
3604 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303605 }
3606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003608 pthread_mutex_lock(&adev->lock);
3609 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3610 ret = voice_extn_compress_voip_start_input_stream(in);
3611 else
3612 ret = start_input_stream(in);
3613 pthread_mutex_unlock(&adev->lock);
3614 if (ret != 0) {
3615 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 }
3617 in->standby = 0;
3618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003620 // what's the duration requested by the client?
3621 long ns = 0;
3622
3623 if (in->config.rate)
3624 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3625 in->config.rate;
3626
3627 request_in_focus(in, ns);
3628 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303631 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003632 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303633 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003634 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003635 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003636 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303637 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003638 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303639 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3640 if (bytes % 4 == 0) {
3641 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3642 int_buf_stream = buffer;
Yamit Mehtaa0d653a2016-11-25 20:33:25 +05303643 size_t itt = 0;
3644 for (itt = 0; itt < bytes/4 ; itt++) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303645 int_buf_stream[itt] >>= 8;
3646 }
3647 } else {
3648 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3649 ret = -EINVAL;
3650 goto exit;
3651 }
3652 } if (ret < 0) {
3653 ret = -errno;
3654 }
3655 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 }
3657
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003658 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 /*
3661 * Instead of writing zeroes here, we could trust the hardware
3662 * to always provide zeroes when muted.
3663 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303664 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3665 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 memset(buffer, 0, bytes);
3667
3668exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303669 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303670 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003671 if (-ENETRESET == ret)
3672 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 pthread_mutex_unlock(&in->lock);
3675
3676 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303677 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303678 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303679 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303680 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303681 in->standby = true;
3682 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303683 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003685 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303686 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303687 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 }
3689 return bytes;
3690}
3691
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003692static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693{
3694 return 0;
3695}
3696
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003697static int add_remove_audio_effect(const struct audio_stream *stream,
3698 effect_handle_t effect,
3699 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003701 struct stream_in *in = (struct stream_in *)stream;
3702 int status = 0;
3703 effect_descriptor_t desc;
3704
3705 status = (*effect)->get_descriptor(effect, &desc);
3706 if (status != 0)
3707 return status;
3708
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003709 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003710 pthread_mutex_lock(&in->dev->lock);
3711 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3712 in->enable_aec != enable &&
3713 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3714 in->enable_aec = enable;
3715 if (!in->standby)
3716 select_devices(in->dev, in->usecase);
3717 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003718 if (in->enable_ns != enable &&
3719 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3720 in->enable_ns = enable;
3721 if (!in->standby)
3722 select_devices(in->dev, in->usecase);
3723 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003724 pthread_mutex_unlock(&in->dev->lock);
3725 pthread_mutex_unlock(&in->lock);
3726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 return 0;
3728}
3729
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003730static int in_add_audio_effect(const struct audio_stream *stream,
3731 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732{
Eric Laurent994a6932013-07-17 11:51:42 -07003733 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003734 return add_remove_audio_effect(stream, effect, true);
3735}
3736
3737static int in_remove_audio_effect(const struct audio_stream *stream,
3738 effect_handle_t effect)
3739{
Eric Laurent994a6932013-07-17 11:51:42 -07003740 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003741 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742}
3743
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303744int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 audio_io_handle_t handle,
3746 audio_devices_t devices,
3747 audio_output_flags_t flags,
3748 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003749 struct audio_stream_out **stream_out,
3750 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751{
3752 struct audio_device *adev = (struct audio_device *)dev;
3753 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303754 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003755 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303758
3759 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3760 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003761 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303762 return -EINVAL;
3763 }
3764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3766
Mingming Yin3a941d42016-02-17 18:08:05 -08003767 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3768 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303769 devices, flags, &out->stream);
3770
3771
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003772 if (!out) {
3773 return -ENOMEM;
3774 }
3775
Haynes Mathew George204045b2015-02-25 20:32:03 -08003776 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003777 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003778 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 if (devices == AUDIO_DEVICE_NONE)
3781 devices = AUDIO_DEVICE_OUT_SPEAKER;
3782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 out->flags = flags;
3784 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003785 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003786 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003787 out->sample_rate = config->sample_rate;
3788 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3789 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003790 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003791 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003792 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303793 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794
Mingming Yin3a941d42016-02-17 18:08:05 -08003795 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3796 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3797 pthread_mutex_lock(&adev->lock);
3798 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3799 ret = read_hdmi_sink_caps(out);
3800 pthread_mutex_unlock(&adev->lock);
3801 if (ret != 0) {
3802 if (ret == -ENOSYS) {
3803 /* ignore and go with default */
3804 ret = 0;
3805 } else {
3806 ALOGE("error reading hdmi sink caps");
3807 goto error_open;
3808 }
3809 }
3810 }
3811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003813 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303814 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3815 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003816 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3817 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3818
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003819 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003820 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3821 /*
3822 * Do not handle stereo output in Multi-channel cases
3823 * Stereo case is handled in normal playback path
3824 */
3825 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3826 ret = AUDIO_CHANNEL_OUT_STEREO;
3827 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003828
3829 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3830 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003831 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003832 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003833 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003834
3835 if (config->sample_rate == 0)
3836 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3837 if (config->channel_mask == 0)
3838 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003839 if (config->format == 0)
3840 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003841
3842 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003843 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003844 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3846 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003848 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003850 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3851 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003852 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003853 ret = voice_extn_compress_voip_open_output_stream(out);
3854 if (ret != 0) {
3855 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3856 __func__, ret);
3857 goto error_open;
3858 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003859 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3860 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3861
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3863 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3864 ALOGE("%s: Unsupported Offload information", __func__);
3865 ret = -EINVAL;
3866 goto error_open;
3867 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003868
Mingming Yin3a941d42016-02-17 18:08:05 -08003869 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003870 if(config->offload_info.format == 0)
3871 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003872 if (config->offload_info.sample_rate == 0)
3873 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003874 }
3875
Mingming Yin90310102013-11-13 16:57:00 -08003876 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303877 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003878 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003879 ret = -EINVAL;
3880 goto error_open;
3881 }
3882
3883 out->compr_config.codec = (struct snd_codec *)
3884 calloc(1, sizeof(struct snd_codec));
3885
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003886 if (!out->compr_config.codec) {
3887 ret = -ENOMEM;
3888 goto error_open;
3889 }
3890
vivek mehta0ea887a2015-08-26 14:01:20 -07003891 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303892 out->stream.pause = out_pause;
3893 out->stream.flush = out_flush;
3894 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003895 out->usecase = get_offload_usecase(adev, true);
3896 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003897 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003898 out->stream.set_callback = out_set_callback;
3899 out->stream.pause = out_pause;
3900 out->stream.resume = out_resume;
3901 out->stream.drain = out_drain;
3902 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003903 out->usecase = get_offload_usecase(adev, false);
3904 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003905 }
vivek mehta446c3962015-09-14 10:57:35 -07003906
3907 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003908 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3909 config->format == 0 && config->sample_rate == 0 &&
3910 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003911 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003912 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3913 } else {
3914 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3915 ret = -EEXIST;
3916 goto error_open;
3917 }
vivek mehta446c3962015-09-14 10:57:35 -07003918 }
3919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920 if (config->offload_info.channel_mask)
3921 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003922 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003923 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003924 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003925 } else {
3926 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3927 ret = -EINVAL;
3928 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003929 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003930
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003931 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003932 out->sample_rate = config->offload_info.sample_rate;
3933
Mingming Yin3ee55c62014-08-04 14:23:35 -07003934 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003935
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303936 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3937 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3938 audio_extn_dolby_send_ddp_endp_params(adev);
3939 audio_extn_dolby_set_dmid(adev);
3940 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003941
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003942 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003943 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003944 out->compr_config.codec->bit_rate =
3945 config->offload_info.bit_rate;
3946 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303947 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303949 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003950 /*TODO: Do we need to change it for passthrough */
3951 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003952
Manish Dewangana6fc5442015-08-24 20:30:31 +05303953 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3954 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3955 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3956 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303957
3958 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3959 AUDIO_FORMAT_PCM) {
3960
3961 /*Based on platform support, configure appropriate alsa format for corresponding
3962 *hal input format.
3963 */
3964 out->compr_config.codec->format = hal_format_to_alsa(
3965 config->offload_info.format);
3966
Ashish Jain83a6cc22016-06-28 14:34:17 +05303967 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303968 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303969 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303970
3971 /*for direct PCM playback populate bit_width based on selected alsa format as
3972 *hal input format and alsa format might differ based on platform support.
3973 */
3974 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303975 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303976
3977 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3978
3979 /* Check if alsa session is configured with the same format as HAL input format,
3980 * if not then derive correct fragment size needed to accomodate the
3981 * conversion of HAL input format to alsa format.
3982 */
3983 audio_extn_utils_update_direct_pcm_fragment_size(out);
3984
3985 /*if hal input and output fragment size is different this indicates HAL input format is
3986 *not same as the alsa format
3987 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303988 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303989 /*Allocate a buffer to convert input data to the alsa configured format.
3990 *size of convert buffer is equal to the size required to hold one fragment size
3991 *worth of pcm data, this is because flinger does not write more than fragment_size
3992 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303993 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3994 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303995 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3996 ret = -ENOMEM;
3997 goto error_open;
3998 }
3999 }
4000 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4001 out->compr_config.fragment_size =
4002 audio_extn_passthru_get_buffer_size(&config->offload_info);
4003 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4004 } else {
4005 out->compr_config.fragment_size =
4006 platform_get_compress_offload_buffer_size(&config->offload_info);
4007 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4008 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004009
Amit Shekhar6f461b12014-08-01 14:52:58 -07004010 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304011 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004012
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004013 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4014 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004015
Alexy Josephaa54c872014-12-03 02:46:47 -08004016
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004017 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304018 out->send_next_track_params = false;
4019 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004020 out->offload_state = OFFLOAD_STATE_IDLE;
4021 out->playback_started = 0;
4022
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004023 audio_extn_dts_create_state_notifier_node(out->usecase);
4024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004025 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4026 __func__, config->offload_info.version,
4027 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304028
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304029 /* Check if DSD audio format is supported in codec
4030 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304031 */
4032
4033 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304034 (!platform_check_codec_dsd_support(adev->platform) ||
4035 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304036 ret = -EINVAL;
4037 goto error_open;
4038 }
4039
Ashish Jain5106d362016-05-11 19:23:33 +05304040 /* Disable gapless if any of the following is true
4041 * passthrough playback
4042 * AV playback
4043 * Direct PCM playback
4044 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304045 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304046 (config->format == AUDIO_FORMAT_DSD) ||
4047 config->offload_info.has_video ||
4048 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304049 check_and_set_gapless_mode(adev, false);
4050 } else
4051 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004052
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304053 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004054 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4055 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304056 if (config->format == AUDIO_FORMAT_DSD) {
4057 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4058 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4059 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004060
4061 create_offload_callback_thread(out);
4062
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004063 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304064 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004065 if (ret != 0) {
4066 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4067 __func__, ret);
4068 goto error_open;
4069 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004070 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4071 if (config->sample_rate == 0)
4072 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4073 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4074 config->sample_rate != 8000) {
4075 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4076 ret = -EINVAL;
4077 goto error_open;
4078 }
4079 out->sample_rate = config->sample_rate;
4080 out->config.rate = config->sample_rate;
4081 if (config->format == AUDIO_FORMAT_DEFAULT)
4082 config->format = AUDIO_FORMAT_PCM_16_BIT;
4083 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4084 config->format = AUDIO_FORMAT_PCM_16_BIT;
4085 ret = -EINVAL;
4086 goto error_open;
4087 }
4088 out->format = config->format;
4089 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4090 out->config = pcm_config_afe_proxy_playback;
4091 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004092 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304093 unsigned int channels = 0;
4094 /*Update config params to default if not set by the caller*/
4095 if (config->sample_rate == 0)
4096 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4097 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4098 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4099 if (config->format == AUDIO_FORMAT_DEFAULT)
4100 config->format = AUDIO_FORMAT_PCM_16_BIT;
4101
4102 channels = audio_channel_count_from_out_mask(out->channel_mask);
4103
Ashish Jain83a6cc22016-06-28 14:34:17 +05304104 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4105 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004106 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4107 out->flags);
4108 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304109 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4110 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4111 out->config = pcm_config_low_latency;
4112 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4113 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4114 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304115 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4116 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4117 if (out->config.period_size <= 0) {
4118 ALOGE("Invalid configuration period size is not valid");
4119 ret = -EINVAL;
4120 goto error_open;
4121 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304122 } else {
4123 /* primary path is the default path selected if no other outputs are available/suitable */
4124 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4125 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4126 }
4127 out->hal_ip_format = format = out->format;
4128 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4129 out->hal_op_format = pcm_format_to_hal(out->config.format);
4130 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4131 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004132 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304133 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304134 if (out->hal_ip_format != out->hal_op_format) {
4135 uint32_t buffer_size = out->config.period_size *
4136 format_to_bitwidth_table[out->hal_op_format] *
4137 out->config.channels;
4138 out->convert_buffer = calloc(1, buffer_size);
4139 if (out->convert_buffer == NULL){
4140 ALOGE("Allocation failed for convert buffer for size %d",
4141 out->compr_config.fragment_size);
4142 ret = -ENOMEM;
4143 goto error_open;
4144 }
4145 ALOGD("Convert buffer allocated of size %d", buffer_size);
4146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 }
4148
Ashish Jain83a6cc22016-06-28 14:34:17 +05304149 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4150 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4151
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004152 /* TODO remove this hardcoding and check why width is zero*/
4153 if (out->bit_width == 0)
4154 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304155 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004156 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004157 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304158 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304159 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004160 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4161 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4162 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004163 if(adev->primary_output == NULL)
4164 adev->primary_output = out;
4165 else {
4166 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004167 ret = -EEXIST;
4168 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004169 }
4170 }
4171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 /* Check if this usecase is already existing */
4173 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004174 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4175 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004178 ret = -EEXIST;
4179 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 }
4181 pthread_mutex_unlock(&adev->lock);
4182
4183 out->stream.common.get_sample_rate = out_get_sample_rate;
4184 out->stream.common.set_sample_rate = out_set_sample_rate;
4185 out->stream.common.get_buffer_size = out_get_buffer_size;
4186 out->stream.common.get_channels = out_get_channels;
4187 out->stream.common.get_format = out_get_format;
4188 out->stream.common.set_format = out_set_format;
4189 out->stream.common.standby = out_standby;
4190 out->stream.common.dump = out_dump;
4191 out->stream.common.set_parameters = out_set_parameters;
4192 out->stream.common.get_parameters = out_get_parameters;
4193 out->stream.common.add_audio_effect = out_add_audio_effect;
4194 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4195 out->stream.get_latency = out_get_latency;
4196 out->stream.set_volume = out_set_volume;
4197 out->stream.write = out_write;
4198 out->stream.get_render_position = out_get_render_position;
4199 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004200 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004202 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004204 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004205 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206
4207 config->format = out->stream.common.get_format(&out->stream.common);
4208 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4209 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4210
4211 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304212 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004213 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004214
4215 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4216 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4217 popcount(out->channel_mask), out->playback_started);
4218
Eric Laurent994a6932013-07-17 11:51:42 -07004219 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004221
4222error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304223 if (out->convert_buffer)
4224 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004225 free(out);
4226 *stream_out = NULL;
4227 ALOGD("%s: exit: ret %d", __func__, ret);
4228 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229}
4230
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304231void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 struct audio_stream_out *stream)
4233{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004234 struct stream_out *out = (struct stream_out *)stream;
4235 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004236 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004237
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304238 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4239
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004240 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304241 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004242 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304243 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004244 if(ret != 0)
4245 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4246 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004247 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004248 out_standby(&stream->common);
4249
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004250 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004251 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004252 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004253 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004254 if (out->compr_config.codec != NULL)
4255 free(out->compr_config.codec);
4256 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004257
Ashish Jain83a6cc22016-06-28 14:34:17 +05304258 if (out->convert_buffer != NULL) {
4259 free(out->convert_buffer);
4260 out->convert_buffer = NULL;
4261 }
4262
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004263 if (adev->voice_tx_output == out)
4264 adev->voice_tx_output = NULL;
4265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004266 pthread_cond_destroy(&out->cond);
4267 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004269 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270}
4271
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004272static void close_compress_sessions(struct audio_device *adev)
4273{
Mingming Yin7b762e72015-03-04 13:47:32 -08004274 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304275 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004276 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004277 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304278
4279 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004280 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304281 if (is_offload_usecase(usecase->id)) {
4282 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004283 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4284 out = usecase->stream.out;
4285 pthread_mutex_unlock(&adev->lock);
4286 out_standby(&out->stream.common);
4287 pthread_mutex_lock(&adev->lock);
4288 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304289 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004290 }
4291 pthread_mutex_unlock(&adev->lock);
4292}
4293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4295{
4296 struct audio_device *adev = (struct audio_device *)dev;
4297 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004299 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004300 int ret;
4301 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004303 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304306 if (!parms)
4307 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004308 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4309 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304310 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304311 if (strstr(snd_card_status, "OFFLINE")) {
4312 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304313 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004314 //close compress sessions on OFFLINE status
4315 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304316 } else if (strstr(snd_card_status, "ONLINE")) {
4317 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304318 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004319 //send dts hpx license if enabled
4320 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304321 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304322 }
4323
4324 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004325 status = voice_set_parameters(adev, parms);
4326 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004327 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004329 status = platform_set_parameters(adev->platform, parms);
4330 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004331 goto done;
4332
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004333 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4334 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004335 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4337 adev->bluetooth_nrec = true;
4338 else
4339 adev->bluetooth_nrec = false;
4340 }
4341
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004342 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4343 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4345 adev->screen_off = false;
4346 else
4347 adev->screen_off = true;
4348 }
4349
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004350 ret = str_parms_get_int(parms, "rotation", &val);
4351 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004352 bool reverse_speakers = false;
4353 switch(val) {
4354 // FIXME: note that the code below assumes that the speakers are in the correct placement
4355 // relative to the user when the device is rotated 90deg from its default rotation. This
4356 // assumption is device-specific, not platform-specific like this code.
4357 case 270:
4358 reverse_speakers = true;
4359 break;
4360 case 0:
4361 case 90:
4362 case 180:
4363 break;
4364 default:
4365 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004366 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004367 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004368 if (status == 0) {
4369 if (adev->speaker_lr_swap != reverse_speakers) {
4370 adev->speaker_lr_swap = reverse_speakers;
4371 // only update the selected device if there is active pcm playback
4372 struct audio_usecase *usecase;
4373 struct listnode *node;
4374 list_for_each(node, &adev->usecase_list) {
4375 usecase = node_to_item(node, struct audio_usecase, list);
4376 if (usecase->type == PCM_PLAYBACK) {
4377 select_devices(adev, usecase->id);
4378 break;
4379 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004380 }
4381 }
4382 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004383 }
4384
Mingming Yin514a8bc2014-07-29 15:22:21 -07004385 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4386 if (ret >= 0) {
4387 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4388 adev->bt_wb_speech_enabled = true;
4389 else
4390 adev->bt_wb_speech_enabled = false;
4391 }
4392
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004393 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4394 if (ret >= 0) {
4395 val = atoi(value);
4396 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004397 ALOGV("cache new ext disp type and edid");
4398 ret = platform_get_ext_disp_type(adev->platform);
4399 if (ret < 0) {
4400 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004401 status = ret;
4402 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004403 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004404 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004405 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004406 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004407 /*
4408 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4409 * Per AudioPolicyManager, USB device is higher priority than WFD.
4410 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4411 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4412 * starting voice call on USB
4413 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004414 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4415 if (ret >= 0) {
4416 audio_extn_usb_add_device(val, atoi(value));
4417 }
vivek mehta344576a2016-04-12 18:56:03 -07004418 ALOGV("detected USB connect .. disable proxy");
4419 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004420 }
4421 }
4422
4423 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4424 if (ret >= 0) {
4425 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004426 /*
4427 * The HDMI / Displayport disconnect handling has been moved to
4428 * audio extension to ensure that its parameters are not
4429 * invalidated prior to updating sysfs of the disconnect event
4430 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4431 */
4432 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004433 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004434 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4435 if (ret >= 0) {
4436 audio_extn_usb_remove_device(val, atoi(value));
4437 }
vivek mehta344576a2016-04-12 18:56:03 -07004438 ALOGV("detected USB disconnect .. enable proxy");
4439 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004440 }
4441 }
4442
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304443 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4444 if (ret >= 0) {
4445 struct audio_usecase *usecase;
4446 struct listnode *node;
4447 list_for_each(node, &adev->usecase_list) {
4448 usecase = node_to_item(node, struct audio_usecase, list);
4449 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004450 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304451 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304452 lock_output_stream(usecase->stream.out);
4453 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304454 //force device switch to re configure encoder
4455 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304456 audio_extn_a2dp_set_handoff_mode(false);
4457 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304458 break;
4459 }
4460 }
4461 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304462 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004463done:
4464 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004465 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304466error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004467 ALOGV("%s: exit with code(%d)", __func__, status);
4468 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469}
4470
4471static char* adev_get_parameters(const struct audio_hw_device *dev,
4472 const char *keys)
4473{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004474 struct audio_device *adev = (struct audio_device *)dev;
4475 struct str_parms *reply = str_parms_create();
4476 struct str_parms *query = str_parms_create_str(keys);
4477 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304478 char value[256] = {0};
4479 int ret = 0;
4480
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004481 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004482 if (reply) {
4483 str_parms_destroy(reply);
4484 }
4485 if (query) {
4486 str_parms_destroy(query);
4487 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004488 ALOGE("adev_get_parameters: failed to create query or reply");
4489 return NULL;
4490 }
4491
Naresh Tannirud7205b62014-06-20 02:54:48 +05304492 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4493 sizeof(value));
4494 if (ret >=0) {
4495 int val = 1;
4496 pthread_mutex_lock(&adev->snd_card_status.lock);
4497 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4498 val = 0;
4499 pthread_mutex_unlock(&adev->snd_card_status.lock);
4500 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4501 goto exit;
4502 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004503
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004504 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004505 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004506 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004507 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304508 pthread_mutex_unlock(&adev->lock);
4509
Naresh Tannirud7205b62014-06-20 02:54:48 +05304510exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004511 str = str_parms_to_str(reply);
4512 str_parms_destroy(query);
4513 str_parms_destroy(reply);
4514
4515 ALOGV("%s: exit: returns - %s", __func__, str);
4516 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517}
4518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004519static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520{
4521 return 0;
4522}
4523
4524static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4525{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004526 int ret;
4527 struct audio_device *adev = (struct audio_device *)dev;
4528 pthread_mutex_lock(&adev->lock);
4529 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004530 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004531 pthread_mutex_unlock(&adev->lock);
4532 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533}
4534
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004535static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4536 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004537{
4538 return -ENOSYS;
4539}
4540
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004541static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4542 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543{
4544 return -ENOSYS;
4545}
4546
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004547static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4548 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549{
4550 return -ENOSYS;
4551}
4552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004553static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4554 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555{
4556 return -ENOSYS;
4557}
4558
4559static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4560{
4561 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 pthread_mutex_lock(&adev->lock);
4564 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004565 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004567 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004568 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004569 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004570 adev->current_call_output = NULL;
4571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 }
4573 pthread_mutex_unlock(&adev->lock);
4574 return 0;
4575}
4576
4577static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4578{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004579 int ret;
4580
4581 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004582 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004583 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4584 pthread_mutex_unlock(&adev->lock);
4585
4586 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587}
4588
4589static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4590{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004591 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 return 0;
4593}
4594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004595static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 const struct audio_config *config)
4597{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004598 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004600 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4601 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602}
4603
4604static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004605 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 audio_devices_t devices,
4607 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004608 struct audio_stream_in **stream_in,
4609 audio_input_flags_t flags __unused,
4610 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004611 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612{
4613 struct audio_device *adev = (struct audio_device *)dev;
4614 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004615 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004616 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004617 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304618 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304621 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4622 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625
4626 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004627
4628 if (!in) {
4629 ALOGE("failed to allocate input stream");
4630 return -ENOMEM;
4631 }
4632
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304633 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304634 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4635 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004636 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004637 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639 in->stream.common.get_sample_rate = in_get_sample_rate;
4640 in->stream.common.set_sample_rate = in_set_sample_rate;
4641 in->stream.common.get_buffer_size = in_get_buffer_size;
4642 in->stream.common.get_channels = in_get_channels;
4643 in->stream.common.get_format = in_get_format;
4644 in->stream.common.set_format = in_set_format;
4645 in->stream.common.standby = in_standby;
4646 in->stream.common.dump = in_dump;
4647 in->stream.common.set_parameters = in_set_parameters;
4648 in->stream.common.get_parameters = in_get_parameters;
4649 in->stream.common.add_audio_effect = in_add_audio_effect;
4650 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4651 in->stream.set_gain = in_set_gain;
4652 in->stream.read = in_read;
4653 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4654
4655 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004656 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 in->standby = 1;
4659 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004660 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004661 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662
4663 /* Update config params with the requested sample rate and channels */
4664 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004665 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4666 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4667 is_low_latency = true;
4668#if LOW_LATENCY_CAPTURE_USE_CASE
4669 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4670#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004671 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004672 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004673
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004674 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004675 if (in->realtime) {
4676 in->config = pcm_config_audio_capture_rt;
4677 in->sample_rate = in->config.rate;
4678 in->af_period_multiplier = af_period_multiplier;
4679 } else {
4680 in->config = pcm_config_audio_capture;
4681 in->config.rate = config->sample_rate;
4682 in->sample_rate = config->sample_rate;
4683 in->af_period_multiplier = 1;
4684 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304685 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004687 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304688 if (adev->mode != AUDIO_MODE_IN_CALL) {
4689 ret = -EINVAL;
4690 goto err_open;
4691 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004692 if (config->sample_rate == 0)
4693 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4694 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4695 config->sample_rate != 8000) {
4696 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4697 ret = -EINVAL;
4698 goto err_open;
4699 }
4700 if (config->format == AUDIO_FORMAT_DEFAULT)
4701 config->format = AUDIO_FORMAT_PCM_16_BIT;
4702 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4703 config->format = AUDIO_FORMAT_PCM_16_BIT;
4704 ret = -EINVAL;
4705 goto err_open;
4706 }
4707
4708 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4709 in->config = pcm_config_afe_proxy_record;
4710 in->config.channels = channel_count;
4711 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304712 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304713 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4714 in, config, &channel_mask_updated)) {
4715 if (channel_mask_updated == true) {
4716 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4717 __func__, config->channel_mask);
4718 ret = -EINVAL;
4719 goto err_open;
4720 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304721 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004722 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004723 audio_extn_compr_cap_format_supported(config->format) &&
4724 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004725 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004726 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304727 /* restrict 24 bit capture for unprocessed source only
4728 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4729 */
4730 if (config->format == AUDIO_FORMAT_DEFAULT) {
4731 config->format = AUDIO_FORMAT_PCM_16_BIT;
4732 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4733 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4734 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4735 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4736 bool ret_error = false;
4737 in->bit_width = 24;
4738 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4739 from HAL is 24_packed and 8_24
4740 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4741 24_packed return error indicating supported format is 24_packed
4742 *> In case of any other source requesting 24 bit or float return error
4743 indicating format supported is 16 bit only.
4744
4745 on error flinger will retry with supported format passed
4746 */
4747 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4748 (source != AUDIO_SOURCE_CAMCORDER)) {
4749 config->format = AUDIO_FORMAT_PCM_16_BIT;
4750 if( config->sample_rate > 48000)
4751 config->sample_rate = 48000;
4752 ret_error = true;
4753 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4754 in->config.format = PCM_FORMAT_S24_3LE;
4755 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4756 in->config.format = PCM_FORMAT_S24_LE;
4757 } else {
4758 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4759 ret_error = true;
4760 }
4761
4762 if (ret_error) {
4763 ret = -EINVAL;
4764 goto err_open;
4765 }
4766 }
4767
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004768 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004769 if (!in->realtime) {
4770 in->format = config->format;
4771 frame_size = audio_stream_in_frame_size(&in->stream);
4772 buffer_size = get_input_buffer_size(config->sample_rate,
4773 config->format,
4774 channel_count,
4775 is_low_latency);
4776 in->config.period_size = buffer_size / frame_size;
4777 }
4778
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004779 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4780 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4781 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004782 (in->config.rate == 8000 || in->config.rate == 16000 ||
4783 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004784 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4785 voice_extn_compress_voip_open_input_stream(in);
4786 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304789 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4790 &adev->streams_input_cfg_list,
4791 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304792 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304793
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004794 /* This stream could be for sound trigger lab,
4795 get sound trigger pcm if present */
4796 audio_extn_sound_trigger_check_and_get_session(in);
4797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004799 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004800 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801
4802err_open:
4803 free(in);
4804 *stream_in = NULL;
4805 return ret;
4806}
4807
4808static void adev_close_input_stream(struct audio_hw_device *dev,
4809 struct audio_stream_in *stream)
4810{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004811 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004812 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004813 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304814
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304815 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004816
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304817 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004818 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304819
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004820 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304821 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004822 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304823 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004824 if (ret != 0)
4825 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4826 __func__, ret);
4827 } else
4828 in_standby(&stream->common);
4829
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004830 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004831 audio_extn_ssr_deinit();
4832 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833
Mingming Yine62d7842013-10-25 16:26:03 -07004834 if(audio_extn_compr_cap_enabled() &&
4835 audio_extn_compr_cap_format_supported(in->config.format))
4836 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004837
Mingming Yinfd7607b2016-01-22 12:48:44 -08004838 if (in->is_st_session) {
4839 ALOGV("%s: sound trigger pcm stop lab", __func__);
4840 audio_extn_sound_trigger_stop_lab(in);
4841 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004842 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843 return;
4844}
4845
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004846static int adev_dump(const audio_hw_device_t *device __unused,
4847 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848{
4849 return 0;
4850}
4851
4852static int adev_close(hw_device_t *device)
4853{
4854 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004855
4856 if (!adev)
4857 return 0;
4858
4859 pthread_mutex_lock(&adev_init_lock);
4860
4861 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004862 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004863 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304864 audio_extn_utils_release_streams_cfg_lists(
4865 &adev->streams_output_cfg_list,
4866 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304867 if (audio_extn_qaf_is_enabled())
4868 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004869 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004870 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004871 free(adev->snd_dev_ref_cnt);
4872 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004873 if (adev->adm_deinit)
4874 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004875 free(device);
4876 adev = NULL;
4877 }
4878 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880 return 0;
4881}
4882
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004883/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4884 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4885 * just that it _might_ work.
4886 */
4887static int period_size_is_plausible_for_low_latency(int period_size)
4888{
4889 switch (period_size) {
4890 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004891 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004892 case 240:
4893 case 320:
4894 case 480:
4895 return 1;
4896 default:
4897 return 0;
4898 }
4899}
4900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901static int adev_open(const hw_module_t *module, const char *name,
4902 hw_device_t **device)
4903{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304904 int ret;
4905
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004906 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4908
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004909 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004910 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004911 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004912 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004913 ALOGD("%s: returning existing instance of adev", __func__);
4914 ALOGD("%s: exit", __func__);
4915 pthread_mutex_unlock(&adev_init_lock);
4916 return 0;
4917 }
4918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 adev = calloc(1, sizeof(struct audio_device));
4920
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004921 if (!adev) {
4922 pthread_mutex_unlock(&adev_init_lock);
4923 return -ENOMEM;
4924 }
4925
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004926 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4929 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4930 adev->device.common.module = (struct hw_module_t *)module;
4931 adev->device.common.close = adev_close;
4932
4933 adev->device.init_check = adev_init_check;
4934 adev->device.set_voice_volume = adev_set_voice_volume;
4935 adev->device.set_master_volume = adev_set_master_volume;
4936 adev->device.get_master_volume = adev_get_master_volume;
4937 adev->device.set_master_mute = adev_set_master_mute;
4938 adev->device.get_master_mute = adev_get_master_mute;
4939 adev->device.set_mode = adev_set_mode;
4940 adev->device.set_mic_mute = adev_set_mic_mute;
4941 adev->device.get_mic_mute = adev_get_mic_mute;
4942 adev->device.set_parameters = adev_set_parameters;
4943 adev->device.get_parameters = adev_get_parameters;
4944 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4945 adev->device.open_output_stream = adev_open_output_stream;
4946 adev->device.close_output_stream = adev_close_output_stream;
4947 adev->device.open_input_stream = adev_open_input_stream;
4948 adev->device.close_input_stream = adev_close_input_stream;
4949 adev->device.dump = adev_dump;
4950
4951 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004952 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004953 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004954 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004957 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004958 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004959 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004960 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004961 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004962 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004963 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004964 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304965 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304966 adev->perf_lock_opts[0] = 0x101;
4967 adev->perf_lock_opts[1] = 0x20E;
4968 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304969
4970 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4971 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004973 adev->platform = platform_init(adev);
4974 if (!adev->platform) {
4975 free(adev->snd_dev_ref_cnt);
4976 free(adev);
4977 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4978 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004979 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304980 pthread_mutex_destroy(&adev->lock);
4981 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004982 return -EINVAL;
4983 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004984
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304985 if (audio_extn_qaf_is_enabled()) {
4986 ret = audio_extn_qaf_init(adev);
4987 if (ret < 0) {
4988 free(adev);
4989 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4990 *device = NULL;
4991 pthread_mutex_unlock(&adev_init_lock);
4992 pthread_mutex_destroy(&adev->lock);
4993 return ret;
4994 }
4995
4996 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4997 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4998 }
4999
Naresh Tanniru4c630392014-05-12 01:05:52 +05305000 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5001
Eric Laurentc4aef752013-09-12 17:45:53 -07005002 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5003 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5004 if (adev->visualizer_lib == NULL) {
5005 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5006 } else {
5007 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5008 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005009 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005010 "visualizer_hal_start_output");
5011 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005012 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005013 "visualizer_hal_stop_output");
5014 }
5015 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005016 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005017 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005018 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005019
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005020 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5021 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5022 if (adev->offload_effects_lib == NULL) {
5023 ALOGE("%s: DLOPEN failed for %s", __func__,
5024 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5025 } else {
5026 ALOGV("%s: DLOPEN successful for %s", __func__,
5027 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5028 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305029 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005030 "offload_effects_bundle_hal_start_output");
5031 adev->offload_effects_stop_output =
5032 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5033 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005034 adev->offload_effects_set_hpx_state =
5035 (int (*)(bool))dlsym(adev->offload_effects_lib,
5036 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305037 adev->offload_effects_get_parameters =
5038 (void (*)(struct str_parms *, struct str_parms *))
5039 dlsym(adev->offload_effects_lib,
5040 "offload_effects_bundle_get_parameters");
5041 adev->offload_effects_set_parameters =
5042 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5043 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005044 }
5045 }
5046
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005047 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5048 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5049 if (adev->adm_lib == NULL) {
5050 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5051 } else {
5052 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5053 adev->adm_init = (adm_init_t)
5054 dlsym(adev->adm_lib, "adm_init");
5055 adev->adm_deinit = (adm_deinit_t)
5056 dlsym(adev->adm_lib, "adm_deinit");
5057 adev->adm_register_input_stream = (adm_register_input_stream_t)
5058 dlsym(adev->adm_lib, "adm_register_input_stream");
5059 adev->adm_register_output_stream = (adm_register_output_stream_t)
5060 dlsym(adev->adm_lib, "adm_register_output_stream");
5061 adev->adm_deregister_stream = (adm_deregister_stream_t)
5062 dlsym(adev->adm_lib, "adm_deregister_stream");
5063 adev->adm_request_focus = (adm_request_focus_t)
5064 dlsym(adev->adm_lib, "adm_request_focus");
5065 adev->adm_abandon_focus = (adm_abandon_focus_t)
5066 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005067 adev->adm_set_config = (adm_set_config_t)
5068 dlsym(adev->adm_lib, "adm_set_config");
5069 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5070 dlsym(adev->adm_lib, "adm_request_focus_v2");
5071 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5072 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5073 adev->adm_on_routing_change = (adm_on_routing_change_t)
5074 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005075 }
5076 }
5077
Mingming Yin514a8bc2014-07-29 15:22:21 -07005078 adev->bt_wb_speech_enabled = false;
5079
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005080 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081 *device = &adev->device.common;
5082
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305083 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5084 &adev->streams_output_cfg_list,
5085 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005086
Kiran Kandi910e1862013-10-29 13:29:42 -07005087 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005088
5089 char value[PROPERTY_VALUE_MAX];
5090 int trial;
5091 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5092 trial = atoi(value);
5093 if (period_size_is_plausible_for_low_latency(trial)) {
5094 pcm_config_low_latency.period_size = trial;
5095 pcm_config_low_latency.start_threshold = trial / 4;
5096 pcm_config_low_latency.avail_min = trial / 4;
5097 configured_low_latency_capture_period_size = trial;
5098 }
5099 }
5100 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5101 trial = atoi(value);
5102 if (period_size_is_plausible_for_low_latency(trial)) {
5103 configured_low_latency_capture_period_size = trial;
5104 }
5105 }
5106
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005107 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5108 af_period_multiplier = atoi(value);
5109 if (af_period_multiplier < 0)
5110 af_period_multiplier = 2;
5111 else if (af_period_multiplier > 4)
5112 af_period_multiplier = 4;
5113
5114 ALOGV("new period_multiplier = %d", af_period_multiplier);
5115 }
5116
vivek mehta446c3962015-09-14 10:57:35 -07005117 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005118 pthread_mutex_unlock(&adev_init_lock);
5119
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005120 if (adev->adm_init)
5121 adev->adm_data = adev->adm_init();
5122
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305123 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005124 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125 return 0;
5126}
5127
5128static struct hw_module_methods_t hal_module_methods = {
5129 .open = adev_open,
5130};
5131
5132struct audio_module HAL_MODULE_INFO_SYM = {
5133 .common = {
5134 .tag = HARDWARE_MODULE_TAG,
5135 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5136 .hal_api_version = HARDWARE_HAL_API_VERSION,
5137 .id = AUDIO_HARDWARE_MODULE_ID,
5138 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005139 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005140 .methods = &hal_module_methods,
5141 },
5142};