blob: bd393f2d7f59e7c87acbaedc1bb0be7275fa1b7e [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
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301619 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001620 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301621 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001622 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301623 usecase->stream.out->flags,
1624 usecase->stream.out->format,
1625 usecase->stream.out->sample_rate,
1626 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301627 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301628 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001629 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001630
1631 /* Notify device change info to effect clients registered */
1632 audio_extn_gef_notify_device_config(
1633 usecase->stream.out->devices,
1634 usecase->stream.out->channel_mask,
1635 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301636 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001637
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001638 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001639
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001640 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001641 /* Enable aanc only if voice call exists */
1642 if (voice_is_call_state_active(adev))
1643 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1644
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001645 /* Enable sidetone only if other voice/voip call already exists */
1646 if (voice_is_call_state_active(adev) ||
1647 voice_extn_compress_voip_is_started(adev))
1648 voice_set_sidetone(adev, out_snd_device, true);
1649 }
1650
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001651 /* Applicable only on the targets that has external modem.
1652 * Enable device command should be sent to modem only after
1653 * enabling voice call mixer controls
1654 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001655 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001656 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1657 out_snd_device,
1658 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301659 ALOGD("%s: done",__func__);
1660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 return status;
1662}
1663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664static int stop_input_stream(struct stream_in *in)
1665{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301666 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 struct audio_usecase *uc_info;
1668 struct audio_device *adev = in->dev;
1669
Dhananjay Kumard4833242016-10-06 22:09:12 +05301670 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671
Eric Laurent994a6932013-07-17 11:51:42 -07001672 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001673 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 uc_info = get_usecase_from_list(adev, in->usecase);
1675 if (uc_info == NULL) {
1676 ALOGE("%s: Could not find the usecase (%d) in the list",
1677 __func__, in->usecase);
1678 return -EINVAL;
1679 }
1680
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001681 /* Close in-call recording streams */
1682 voice_check_and_stop_incall_rec_usecase(adev, in);
1683
Eric Laurent150dbfe2013-02-27 14:31:02 -08001684 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001685 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001686
1687 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001688 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001690 list_remove(&uc_info->list);
1691 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692
Eric Laurent994a6932013-07-17 11:51:42 -07001693 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 return ret;
1695}
1696
1697int start_input_stream(struct stream_in *in)
1698{
1699 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 struct audio_usecase *uc_info;
1702 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301703 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704
Mingming Yin2664a5b2015-09-03 10:53:11 -07001705 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1706 if (get_usecase_from_list(adev, usecase) == NULL)
1707 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301708 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1709 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001710
Naresh Tanniru80659832014-06-04 18:17:56 +05301711
1712 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301713 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301714 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301715 goto error_config;
1716 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301717
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001718 /* Check if source matches incall recording usecase criteria */
1719 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1720 if (ret)
1721 goto error_config;
1722 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001723 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1724
1725 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1726 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1727 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001728 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001729 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001730
Eric Laurentb23d5282013-05-14 15:27:20 -07001731 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 if (in->pcm_device_id < 0) {
1733 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1734 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001735 ret = -EINVAL;
1736 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001738
1739 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001741
1742 if (!uc_info) {
1743 ret = -ENOMEM;
1744 goto error_config;
1745 }
1746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 uc_info->id = in->usecase;
1748 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001749 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 uc_info->devices = in->device;
1751 uc_info->in_snd_device = SND_DEVICE_NONE;
1752 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001754 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301755 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1756 adev->perf_lock_opts,
1757 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001758 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301760 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1761 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001762
1763 unsigned int flags = PCM_IN;
1764 unsigned int pcm_open_retry_count = 0;
1765
1766 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1767 flags |= PCM_MMAP | PCM_NOIRQ;
1768 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001769 } else if (in->realtime) {
1770 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001771 }
1772
1773 while (1) {
1774 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1775 flags, &in->config);
1776 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1777 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1778 if (in->pcm != NULL) {
1779 pcm_close(in->pcm);
1780 in->pcm = NULL;
1781 }
1782 if (pcm_open_retry_count-- == 0) {
1783 ret = -EIO;
1784 goto error_open;
1785 }
1786 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1787 continue;
1788 }
1789 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001791
1792 ALOGV("%s: pcm_prepare", __func__);
1793 ret = pcm_prepare(in->pcm);
1794 if (ret < 0) {
1795 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1796 pcm_close(in->pcm);
1797 in->pcm = NULL;
1798 goto error_open;
1799 }
1800
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001801 register_in_stream(in);
1802 if (in->realtime) {
1803 ret = pcm_start(in->pcm);
1804 if (ret < 0)
1805 goto error_open;
1806 }
1807
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301808 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001809 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001810
Eric Laurentc8400632013-02-14 19:04:54 -08001811 return ret;
1812
1813error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301814 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001816error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301817 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301818 /*
1819 * sleep 50ms to allow sufficient time for kernel
1820 * drivers to recover incases like SSR.
1821 */
1822 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001824
1825 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826}
1827
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001828void lock_input_stream(struct stream_in *in)
1829{
1830 pthread_mutex_lock(&in->pre_lock);
1831 pthread_mutex_lock(&in->lock);
1832 pthread_mutex_unlock(&in->pre_lock);
1833}
1834
1835void lock_output_stream(struct stream_out *out)
1836{
1837 pthread_mutex_lock(&out->pre_lock);
1838 pthread_mutex_lock(&out->lock);
1839 pthread_mutex_unlock(&out->pre_lock);
1840}
1841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842/* must be called with out->lock locked */
1843static int send_offload_cmd_l(struct stream_out* out, int command)
1844{
1845 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1846
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001847 if (!cmd) {
1848 ALOGE("failed to allocate mem for command 0x%x", command);
1849 return -ENOMEM;
1850 }
1851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001852 ALOGVV("%s %d", __func__, command);
1853
1854 cmd->cmd = command;
1855 list_add_tail(&out->offload_cmd_list, &cmd->node);
1856 pthread_cond_signal(&out->offload_cond);
1857 return 0;
1858}
1859
1860/* must be called iwth out->lock locked */
1861static void stop_compressed_output_l(struct stream_out *out)
1862{
1863 out->offload_state = OFFLOAD_STATE_IDLE;
1864 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001866 if (out->compr != NULL) {
1867 compress_stop(out->compr);
1868 while (out->offload_thread_blocked) {
1869 pthread_cond_wait(&out->cond, &out->lock);
1870 }
1871 }
1872}
1873
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001874bool is_offload_usecase(audio_usecase_t uc_id)
1875{
1876 unsigned int i;
1877 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1878 if (uc_id == offload_usecases[i])
1879 return true;
1880 }
1881 return false;
1882}
1883
vivek mehta446c3962015-09-14 10:57:35 -07001884static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001885{
vivek mehta446c3962015-09-14 10:57:35 -07001886 audio_usecase_t ret_uc = USECASE_INVALID;
1887 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001888 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001889 if (!adev->multi_offload_enable) {
1890 if (is_direct_pcm)
1891 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1892 else
1893 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001894
vivek mehta446c3962015-09-14 10:57:35 -07001895 pthread_mutex_lock(&adev->lock);
1896 if (get_usecase_from_list(adev, ret_uc) != NULL)
1897 ret_uc = USECASE_INVALID;
1898 pthread_mutex_unlock(&adev->lock);
1899
1900 return ret_uc;
1901 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001902
1903 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001904 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1905 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1906 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1907 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001908 break;
1909 }
1910 }
vivek mehta446c3962015-09-14 10:57:35 -07001911
1912 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1913 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001914}
1915
1916static void free_offload_usecase(struct audio_device *adev,
1917 audio_usecase_t uc_id)
1918{
vivek mehta446c3962015-09-14 10:57:35 -07001919 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001920 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001921
1922 if (!adev->multi_offload_enable)
1923 return;
1924
1925 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1926 if (offload_usecases[offload_uc_index] == uc_id) {
1927 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001928 break;
1929 }
1930 }
1931 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1932}
1933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934static void *offload_thread_loop(void *context)
1935{
1936 struct stream_out *out = (struct stream_out *) context;
1937 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001938 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1941 set_sched_policy(0, SP_FOREGROUND);
1942 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1943
1944 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001945 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 for (;;) {
1947 struct offload_cmd *cmd = NULL;
1948 stream_callback_event_t event;
1949 bool send_callback = false;
1950
1951 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1952 __func__, list_empty(&out->offload_cmd_list),
1953 out->offload_state);
1954 if (list_empty(&out->offload_cmd_list)) {
1955 ALOGV("%s SLEEPING", __func__);
1956 pthread_cond_wait(&out->offload_cond, &out->lock);
1957 ALOGV("%s RUNNING", __func__);
1958 continue;
1959 }
1960
1961 item = list_head(&out->offload_cmd_list);
1962 cmd = node_to_item(item, struct offload_cmd, node);
1963 list_remove(item);
1964
1965 ALOGVV("%s STATE %d CMD %d out->compr %p",
1966 __func__, out->offload_state, cmd->cmd, out->compr);
1967
1968 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1969 free(cmd);
1970 break;
1971 }
1972
1973 if (out->compr == NULL) {
1974 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001975 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001976 pthread_cond_signal(&out->cond);
1977 continue;
1978 }
1979 out->offload_thread_blocked = true;
1980 pthread_mutex_unlock(&out->lock);
1981 send_callback = false;
1982 switch(cmd->cmd) {
1983 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001984 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001986 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001987 send_callback = true;
1988 event = STREAM_CBK_EVENT_WRITE_READY;
1989 break;
1990 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001991 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301992 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001993 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301994 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001995 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301996 if (ret < 0)
1997 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301998 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301999 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002000 compress_drain(out->compr);
2001 else
2002 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302003 if (ret != -ENETRESET) {
2004 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302005 pthread_mutex_lock(&out->lock);
2006 out->send_new_metadata = 1;
2007 out->send_next_track_params = true;
2008 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302009 event = STREAM_CBK_EVENT_DRAIN_READY;
2010 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2011 } else
2012 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 break;
2014 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002015 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002017 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 send_callback = true;
2019 event = STREAM_CBK_EVENT_DRAIN_READY;
2020 break;
2021 default:
2022 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2023 break;
2024 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002025 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 out->offload_thread_blocked = false;
2027 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002028 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002029 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002031 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 free(cmd);
2033 }
2034
2035 pthread_cond_signal(&out->cond);
2036 while (!list_empty(&out->offload_cmd_list)) {
2037 item = list_head(&out->offload_cmd_list);
2038 list_remove(item);
2039 free(node_to_item(item, struct offload_cmd, node));
2040 }
2041 pthread_mutex_unlock(&out->lock);
2042
2043 return NULL;
2044}
2045
2046static int create_offload_callback_thread(struct stream_out *out)
2047{
2048 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2049 list_init(&out->offload_cmd_list);
2050 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2051 offload_thread_loop, out);
2052 return 0;
2053}
2054
2055static int destroy_offload_callback_thread(struct stream_out *out)
2056{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002057 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 stop_compressed_output_l(out);
2059 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2060
2061 pthread_mutex_unlock(&out->lock);
2062 pthread_join(out->offload_thread, (void **) NULL);
2063 pthread_cond_destroy(&out->offload_cond);
2064
2065 return 0;
2066}
2067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068static int stop_output_stream(struct stream_out *out)
2069{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302070 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 struct audio_usecase *uc_info;
2072 struct audio_device *adev = out->dev;
2073
Eric Laurent994a6932013-07-17 11:51:42 -07002074 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 uc_info = get_usecase_from_list(adev, out->usecase);
2077 if (uc_info == NULL) {
2078 ALOGE("%s: Could not find the usecase (%d) in the list",
2079 __func__, out->usecase);
2080 return -EINVAL;
2081 }
2082
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002083 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302084 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002085 if (adev->visualizer_stop_output != NULL)
2086 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002087
2088 audio_extn_dts_remove_state_notifier_node(out->usecase);
2089
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002090 if (adev->offload_effects_stop_output != NULL)
2091 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2092 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002093
Eric Laurent150dbfe2013-02-27 14:31:02 -08002094 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002095 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096
2097 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002098 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002100 list_remove(&uc_info->list);
2101 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002103 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302104 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002105 ALOGV("Disable passthrough , reset mixer to pcm");
2106 /* NO_PASSTHROUGH */
2107 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002108 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002109 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2110 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002111
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302112 /* Must be called after removing the usecase from list */
2113 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302114 audio_extn_keep_alive_start();
2115
Eric Laurent994a6932013-07-17 11:51:42 -07002116 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 return ret;
2118}
2119
2120int start_output_stream(struct stream_out *out)
2121{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 struct audio_usecase *uc_info;
2124 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302125 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002127 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2128 ret = -EINVAL;
2129 goto error_config;
2130 }
2131
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302132 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2133 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2134 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302135
Naresh Tanniru80659832014-06-04 18:17:56 +05302136 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302137 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302138 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302139 goto error_config;
2140 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302141
Eric Laurentb23d5282013-05-14 15:27:20 -07002142 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 if (out->pcm_device_id < 0) {
2144 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2145 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002146 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002147 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 }
2149
2150 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002151
2152 if (!uc_info) {
2153 ret = -ENOMEM;
2154 goto error_config;
2155 }
2156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 uc_info->id = out->usecase;
2158 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002159 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 uc_info->devices = out->devices;
2161 uc_info->in_snd_device = SND_DEVICE_NONE;
2162 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002163 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302165 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2166 adev->perf_lock_opts,
2167 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302168
2169 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2170 audio_extn_keep_alive_stop();
2171 if (audio_extn_passthru_is_enabled() &&
2172 audio_extn_passthru_is_passthrough_stream(out)) {
2173 audio_extn_passthru_on_start(out);
2174 audio_extn_passthru_update_stream_configuration(adev, out);
2175 }
2176 }
2177
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002178 select_devices(adev, out->usecase);
2179
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2181 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002182 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002183 unsigned int flags = PCM_OUT;
2184 unsigned int pcm_open_retry_count = 0;
2185 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2186 flags |= PCM_MMAP | PCM_NOIRQ;
2187 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002188 } else if (out->realtime) {
2189 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002190 } else
2191 flags |= PCM_MONOTONIC;
2192
2193 while (1) {
2194 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2195 flags, &out->config);
2196 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2197 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2198 if (out->pcm != NULL) {
2199 pcm_close(out->pcm);
2200 out->pcm = NULL;
2201 }
2202 if (pcm_open_retry_count-- == 0) {
2203 ret = -EIO;
2204 goto error_open;
2205 }
2206 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2207 continue;
2208 }
2209 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002211
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002212 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2213 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002214
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002215 ALOGV("%s: pcm_prepare", __func__);
2216 if (pcm_is_ready(out->pcm)) {
2217 ret = pcm_prepare(out->pcm);
2218 if (ret < 0) {
2219 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2220 pcm_close(out->pcm);
2221 out->pcm = NULL;
2222 goto error_open;
2223 }
2224 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002226 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2227 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002229 out->compr = compress_open(adev->snd_card,
2230 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 COMPRESS_IN, &out->compr_config);
2232 if (out->compr && !is_compress_ready(out->compr)) {
2233 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2234 compress_close(out->compr);
2235 out->compr = NULL;
2236 ret = -EIO;
2237 goto error_open;
2238 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302239 /* compress_open sends params of the track, so reset the flag here */
2240 out->is_compr_metadata_avail = false;
2241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 if (out->offload_callback)
2243 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002244
Fred Oh3f43e742015-03-04 18:42:34 -08002245 /* Since small bufs uses blocking writes, a write will be blocked
2246 for the default max poll time (20s) in the event of an SSR.
2247 Reduce the poll time to observe and deal with SSR faster.
2248 */
Ashish Jain5106d362016-05-11 19:23:33 +05302249 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002250 compress_set_max_poll_wait(out->compr, 1000);
2251 }
2252
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002253 audio_extn_dts_create_state_notifier_node(out->usecase);
2254 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2255 popcount(out->channel_mask),
2256 out->playback_started);
2257
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002258#ifdef DS1_DOLBY_DDP_ENABLED
2259 if (audio_extn_is_dolby_format(out->format))
2260 audio_extn_dolby_send_ddp_endp_params(adev);
2261#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302262 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002263 if (adev->visualizer_start_output != NULL)
2264 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2265 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302266 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002267 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002270
2271 if (ret == 0) {
2272 register_out_stream(out);
2273 if (out->realtime) {
2274 ret = pcm_start(out->pcm);
2275 if (ret < 0)
2276 goto error_open;
2277 }
2278 }
2279
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302280 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002281 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002282
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002283 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302285 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002287error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302288 /*
2289 * sleep 50ms to allow sufficient time for kernel
2290 * drivers to recover incases like SSR.
2291 */
2292 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002293 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294}
2295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296static int check_input_parameters(uint32_t sample_rate,
2297 audio_format_t format,
2298 int channel_count)
2299{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002300 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302302 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2303 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2304 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002305 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302306 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002307
2308 switch (channel_count) {
2309 case 1:
2310 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302311 case 3:
2312 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002313 case 6:
2314 break;
2315 default:
2316 ret = -EINVAL;
2317 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318
2319 switch (sample_rate) {
2320 case 8000:
2321 case 11025:
2322 case 12000:
2323 case 16000:
2324 case 22050:
2325 case 24000:
2326 case 32000:
2327 case 44100:
2328 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302329 case 96000:
2330 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 break;
2332 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002333 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 }
2335
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002336 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337}
2338
2339static size_t get_input_buffer_size(uint32_t sample_rate,
2340 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002341 int channel_count,
2342 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343{
2344 size_t size = 0;
2345
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002346 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2347 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002349 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002350 if (is_low_latency)
2351 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302352
2353 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002355 /* make sure the size is multiple of 32 bytes
2356 * At 48 kHz mono 16-bit PCM:
2357 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2358 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2359 */
2360 size += 0x1f;
2361 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002362
2363 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364}
2365
Ashish Jain058165c2016-09-28 23:18:48 +05302366static size_t get_output_period_size(uint32_t sample_rate,
2367 audio_format_t format,
2368 int channel_count,
2369 int duration /*in millisecs*/)
2370{
2371 size_t size = 0;
2372 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2373
2374 if ((duration == 0) || (sample_rate == 0) ||
2375 (bytes_per_sample == 0) || (channel_count == 0)) {
2376 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2377 bytes_per_sample, channel_count);
2378 return -EINVAL;
2379 }
2380
2381 size = (sample_rate *
2382 duration *
2383 bytes_per_sample *
2384 channel_count) / 1000;
2385 /*
2386 * To have same PCM samples for all channels, the buffer size requires to
2387 * be multiple of (number of channels * bytes per sample)
2388 * For writes to succeed, the buffer must be written at address which is multiple of 32
2389 */
2390 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2391
2392 return (size/(channel_count * bytes_per_sample));
2393}
2394
Ashish Jain5106d362016-05-11 19:23:33 +05302395static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2396{
2397 uint64_t actual_frames_rendered = 0;
2398 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2399
2400 /* This adjustment accounts for buffering after app processor.
2401 * It is based on estimated DSP latency per use case, rather than exact.
2402 */
2403 int64_t platform_latency = platform_render_latency(out->usecase) *
2404 out->sample_rate / 1000000LL;
2405
2406 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2407 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2408 * hence only estimate.
2409 */
2410 int64_t signed_frames = out->written - kernel_buffer_size;
2411
2412 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2413
2414 if (signed_frames > 0)
2415 actual_frames_rendered = signed_frames;
2416
2417 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2418 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2419 (long long int)out->written, (int)kernel_buffer_size,
2420 audio_bytes_per_sample(out->compr_config.codec->format),
2421 popcount(out->channel_mask));
2422
2423 return actual_frames_rendered;
2424}
2425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2427{
2428 struct stream_out *out = (struct stream_out *)stream;
2429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431}
2432
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002433static int out_set_sample_rate(struct audio_stream *stream __unused,
2434 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435{
2436 return -ENOSYS;
2437}
2438
2439static size_t out_get_buffer_size(const struct audio_stream *stream)
2440{
2441 struct stream_out *out = (struct stream_out *)stream;
2442
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002443 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002444 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002445 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2446 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302447 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302448 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002450 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002451 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452}
2453
2454static uint32_t out_get_channels(const struct audio_stream *stream)
2455{
2456 struct stream_out *out = (struct stream_out *)stream;
2457
2458 return out->channel_mask;
2459}
2460
2461static audio_format_t out_get_format(const struct audio_stream *stream)
2462{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 struct stream_out *out = (struct stream_out *)stream;
2464
2465 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466}
2467
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002468static int out_set_format(struct audio_stream *stream __unused,
2469 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470{
2471 return -ENOSYS;
2472}
2473
2474static int out_standby(struct audio_stream *stream)
2475{
2476 struct stream_out *out = (struct stream_out *)stream;
2477 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302479 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2480 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002482 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002484 if (adev->adm_deregister_stream)
2485 adev->adm_deregister_stream(adev->adm_data, out->handle);
2486
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002487 if (is_offload_usecase(out->usecase))
2488 stop_compressed_output_l(out);
2489
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002490 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002492 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2493 voice_extn_compress_voip_close_output_stream(stream);
2494 pthread_mutex_unlock(&adev->lock);
2495 pthread_mutex_unlock(&out->lock);
2496 ALOGD("VOIP output entered standby");
2497 return 0;
2498 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 if (out->pcm) {
2500 pcm_close(out->pcm);
2501 out->pcm = NULL;
2502 }
2503 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002504 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302505 out->send_next_track_params = false;
2506 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002507 out->gapless_mdata.encoder_delay = 0;
2508 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509 if (out->compr != NULL) {
2510 compress_close(out->compr);
2511 out->compr = NULL;
2512 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002513 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002515 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 }
2517 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302518 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 return 0;
2520}
2521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002522static int out_dump(const struct audio_stream *stream __unused,
2523 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524{
2525 return 0;
2526}
2527
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002528static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2529{
2530 int ret = 0;
2531 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002532
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002533 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002534 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002535 return -EINVAL;
2536 }
2537
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302538 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002539
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002540 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2541 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302542 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002543 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002544 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2545 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302546 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002547 }
2548
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002549 ALOGV("%s new encoder delay %u and padding %u", __func__,
2550 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2551
2552 return 0;
2553}
2554
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002555static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2556{
2557 return out == adev->primary_output || out == adev->voice_tx_output;
2558}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2561{
2562 struct stream_out *out = (struct stream_out *)stream;
2563 struct audio_device *adev = out->dev;
2564 struct str_parms *parms;
2565 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002566 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567
sangwoobc677242013-08-08 16:53:43 +09002568 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302571 if (!parms)
2572 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002573 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2574 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002576 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002577 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002579 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002580 * When HDMI cable is unplugged the music playback is paused and
2581 * the policy manager sends routing=0. But the audioflinger continues
2582 * to write data until standby time (3sec). As the HDMI core is
2583 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002584 * Avoid this by routing audio to speaker until standby.
2585 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002586 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2587 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302588 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002589 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2590 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002591 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302592 /*
2593 * When A2DP is disconnected the
2594 * music playback is paused and the policy manager sends routing=0
2595 * But the audioflingercontinues to write data until standby time
2596 * (3sec). As BT is turned off, the write gets blocked.
2597 * Avoid this by routing audio to speaker until standby.
2598 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002599 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302600 (val == AUDIO_DEVICE_NONE)) {
2601 val = AUDIO_DEVICE_OUT_SPEAKER;
2602 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302603 /* To avoid a2dp to sco overlapping force route BT usecases
2604 * to speaker based on Phone state
2605 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002606 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302607 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2608 (adev->mode == AUDIO_MODE_IN_CALL))) {
2609 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2610 val = AUDIO_DEVICE_OUT_SPEAKER;
2611 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002612 /*
2613 * select_devices() call below switches all the usecases on the same
2614 * backend to the new device. Refer to check_usecases_codec_backend() in
2615 * the select_devices(). But how do we undo this?
2616 *
2617 * For example, music playback is active on headset (deep-buffer usecase)
2618 * and if we go to ringtones and select a ringtone, low-latency usecase
2619 * will be started on headset+speaker. As we can't enable headset+speaker
2620 * and headset devices at the same time, select_devices() switches the music
2621 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2622 * So when the ringtone playback is completed, how do we undo the same?
2623 *
2624 * We are relying on the out_set_parameters() call on deep-buffer output,
2625 * once the ringtone playback is ended.
2626 * NOTE: We should not check if the current devices are same as new devices.
2627 * Because select_devices() must be called to switch back the music
2628 * playback to headset.
2629 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002630 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002631 audio_devices_t new_dev = val;
2632 bool same_dev = out->devices == new_dev;
2633 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002634
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002635 if (output_drives_call(adev, out)) {
2636 if(!voice_is_in_call(adev)) {
2637 if (adev->mode == AUDIO_MODE_IN_CALL) {
2638 adev->current_call_output = out;
2639 ret = voice_start_call(adev);
2640 }
2641 } else {
2642 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002643 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002644 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002645 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002646
2647 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002648 if (!same_dev) {
2649 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302650 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2651 adev->perf_lock_opts,
2652 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002653 if (adev->adm_on_routing_change)
2654 adev->adm_on_routing_change(adev->adm_data,
2655 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002656 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002657 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302658 if (!same_dev)
2659 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002660 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002661 }
2662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002664 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002666
2667 if (out == adev->primary_output) {
2668 pthread_mutex_lock(&adev->lock);
2669 audio_extn_set_parameters(adev, parms);
2670 pthread_mutex_unlock(&adev->lock);
2671 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002672 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002673 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002674 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002675
2676 audio_extn_dts_create_state_notifier_node(out->usecase);
2677 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2678 popcount(out->channel_mask),
2679 out->playback_started);
2680
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002681 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002682 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302685error:
Eric Laurent994a6932013-07-17 11:51:42 -07002686 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 return ret;
2688}
2689
2690static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2691{
2692 struct stream_out *out = (struct stream_out *)stream;
2693 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002694 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 char value[256];
2696 struct str_parms *reply = str_parms_create();
2697 size_t i, j;
2698 int ret;
2699 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002700
2701 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002702 if (reply) {
2703 str_parms_destroy(reply);
2704 }
2705 if (query) {
2706 str_parms_destroy(query);
2707 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002708 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2709 return NULL;
2710 }
2711
Eric Laurent994a6932013-07-17 11:51:42 -07002712 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2714 if (ret >= 0) {
2715 value[0] = '\0';
2716 i = 0;
2717 while (out->supported_channel_masks[i] != 0) {
2718 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2719 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2720 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002721 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002723 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 first = false;
2725 break;
2726 }
2727 }
2728 i++;
2729 }
2730 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2731 str = str_parms_to_str(reply);
2732 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002733 voice_extn_out_get_parameters(out, query, reply);
2734 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002735 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002736 free(str);
2737 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002740
Alexy Joseph62142aa2015-11-16 15:10:34 -08002741
2742 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2743 if (ret >= 0) {
2744 value[0] = '\0';
2745 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2746 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302747 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002748 } else {
2749 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302750 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002751 }
2752 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002753 if (str)
2754 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002755 str = str_parms_to_str(reply);
2756 }
2757
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002758 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2759 if (ret >= 0) {
2760 value[0] = '\0';
2761 i = 0;
2762 first = true;
2763 while (out->supported_formats[i] != 0) {
2764 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2765 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2766 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002767 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002768 }
2769 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2770 first = false;
2771 break;
2772 }
2773 }
2774 i++;
2775 }
2776 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002777 if (str)
2778 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002779 str = str_parms_to_str(reply);
2780 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002781
2782 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2783 if (ret >= 0) {
2784 value[0] = '\0';
2785 i = 0;
2786 first = true;
2787 while (out->supported_sample_rates[i] != 0) {
2788 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2789 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2790 if (!first) {
2791 strlcat(value, "|", sizeof(value));
2792 }
2793 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2794 first = false;
2795 break;
2796 }
2797 }
2798 i++;
2799 }
2800 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2801 if (str)
2802 free(str);
2803 str = str_parms_to_str(reply);
2804 }
2805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 str_parms_destroy(query);
2807 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002808 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 return str;
2810}
2811
2812static uint32_t out_get_latency(const struct audio_stream_out *stream)
2813{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002814 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002816 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Alexy Josephaa54c872014-12-03 02:46:47 -08002818 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002819 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002820 } else if (out->realtime) {
2821 // since the buffer won't be filled up faster than realtime,
2822 // return a smaller number
2823 if (out->config.rate)
2824 period_ms = (out->af_period_multiplier * out->config.period_size *
2825 1000) / (out->config.rate);
2826 else
2827 period_ms = 0;
2828 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002829 } else {
2830 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002832 }
2833
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302834 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002835 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836}
2837
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302838static float AmpToDb(float amplification)
2839{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302840 float db = DSD_VOLUME_MIN_DB;
2841 if (amplification > 0) {
2842 db = 20 * log10(amplification);
2843 if(db < DSD_VOLUME_MIN_DB)
2844 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302845 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302846 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302847}
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849static int out_set_volume(struct audio_stream_out *stream, float left,
2850 float right)
2851{
Eric Laurenta9024de2013-04-04 09:19:12 -07002852 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 int volume[2];
2854
Eric Laurenta9024de2013-04-04 09:19:12 -07002855 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2856 /* only take left channel into account: the API is for stereo anyway */
2857 out->muted = (left == 0.0f);
2858 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002859 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302860 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002861 /*
2862 * Set mute or umute on HDMI passthrough stream.
2863 * Only take left channel into account.
2864 * Mute is 0 and unmute 1
2865 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302866 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302867 } else if (out->format == AUDIO_FORMAT_DSD){
2868 char mixer_ctl_name[128] = "DSD Volume";
2869 struct audio_device *adev = out->dev;
2870 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2871
2872 if (!ctl) {
2873 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2874 __func__, mixer_ctl_name);
2875 return -EINVAL;
2876 }
2877 volume[0] = (int)(AmpToDb(left));
2878 volume[1] = (int)(AmpToDb(right));
2879 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2880 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002881 } else {
2882 char mixer_ctl_name[128];
2883 struct audio_device *adev = out->dev;
2884 struct mixer_ctl *ctl;
2885 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002886 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002888 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2889 "Compress Playback %d Volume", pcm_device_id);
2890 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2891 if (!ctl) {
2892 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2893 __func__, mixer_ctl_name);
2894 return -EINVAL;
2895 }
2896 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2897 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2898 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2899 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002901 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903 return -ENOSYS;
2904}
2905
2906static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2907 size_t bytes)
2908{
2909 struct stream_out *out = (struct stream_out *)stream;
2910 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302911 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002912 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002914 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302915
Naresh Tanniru80659832014-06-04 18:17:56 +05302916 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002917
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302918 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302919 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302920 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2921 pthread_mutex_unlock(&out->lock);
2922 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302923 } else {
2924 /* increase written size during SSR to avoid mismatch
2925 * with the written frames count in AF
2926 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002927 // bytes per frame
2928 size_t bpf = audio_bytes_per_sample(out->format) *
2929 audio_channel_count_from_out_mask(out->channel_mask);
2930 if (bpf != 0)
2931 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302932 ALOGD(" %s: sound card is not active/SSR state", __func__);
2933 ret= -EIO;
2934 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302935 }
2936 }
2937
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302938 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302939 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2940 if (audio_bytes_per_sample(out->format) != 0)
2941 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2942 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302943 goto exit;
2944 }
2945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002947 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002948 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002949 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2950 ret = voice_extn_compress_voip_start_output_stream(out);
2951 else
2952 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002953 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002956 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 goto exit;
2958 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002959
2960 if (last_known_cal_step != -1) {
2961 ALOGD("%s: retry previous failed cal level set", __func__);
2962 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2963 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965
Ashish Jain81eb2a82015-05-13 10:52:34 +05302966 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002967 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302968 adev->is_channel_status_set = true;
2969 }
2970
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002971 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002972 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002973 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002974 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002975 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2976 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302977 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2978 ALOGD("copl(%p):send next track params in gapless", out);
2979 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2980 out->send_next_track_params = false;
2981 out->is_compr_metadata_avail = false;
2982 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002983 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302984 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302985 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002986
Ashish Jain83a6cc22016-06-28 14:34:17 +05302987 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302988 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302989 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302990 pthread_mutex_unlock(&out->lock);
2991 return -EINVAL;
2992 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302993 audio_format_t dst_format = out->hal_op_format;
2994 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302995
2996 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2997 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2998
Ashish Jain83a6cc22016-06-28 14:34:17 +05302999 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303000 dst_format,
3001 buffer,
3002 src_format,
3003 frames);
3004
Ashish Jain83a6cc22016-06-28 14:34:17 +05303005 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303006 bytes_to_write);
3007
3008 /*Convert written bytes in audio flinger format*/
3009 if (ret > 0)
3010 ret = ((ret * format_to_bitwidth_table[out->format]) /
3011 format_to_bitwidth_table[dst_format]);
3012 }
3013 } else
3014 ret = compress_write(out->compr, buffer, bytes);
3015
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303016 if (ret < 0)
3017 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303018 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303019 /*msg to cb thread only if non blocking write is enabled*/
3020 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303021 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303023 } else if (-ENETRESET == ret) {
3024 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3025 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3026 pthread_mutex_unlock(&out->lock);
3027 out_standby(&out->stream.common);
3028 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 }
Ashish Jain5106d362016-05-11 19:23:33 +05303030 if ( ret == (ssize_t)bytes && !out->non_blocking)
3031 out->written += bytes;
3032
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303033 /* Call compr start only when non-zero bytes of data is there to be rendered */
3034 if (!out->playback_started && ret > 0) {
3035 int status = compress_start(out->compr);
3036 if (status < 0) {
3037 ret = status;
3038 ALOGE("%s: compr start failed with err %d", __func__, errno);
3039 goto exit;
3040 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003041 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 out->playback_started = 1;
3043 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003044
3045 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3046 popcount(out->channel_mask),
3047 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 }
3049 pthread_mutex_unlock(&out->lock);
3050 return ret;
3051 } else {
3052 if (out->pcm) {
3053 if (out->muted)
3054 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003055
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303056 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003057
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003058 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003059
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003060 if (out->config.rate)
3061 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3062 out->config.rate;
3063
3064 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3065
3066 request_out_focus(out, ns);
3067
3068 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003069 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003070 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303071 out->convert_buffer != NULL) {
3072
3073 memcpy_by_audio_format(out->convert_buffer,
3074 out->hal_op_format,
3075 buffer,
3076 out->hal_ip_format,
3077 out->config.period_size * out->config.channels);
3078
3079 ret = pcm_write(out->pcm, out->convert_buffer,
3080 (out->config.period_size *
3081 out->config.channels *
3082 format_to_bitwidth_table[out->hal_op_format]));
3083 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003084 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303085 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003086
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003087 release_out_focus(out);
3088
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303089 if (ret < 0)
3090 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303091 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3092 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3093 else
3094 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 }
3097
3098exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303099 /* ToDo: There may be a corner case when SSR happens back to back during
3100 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303101 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303102 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303103 }
3104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 pthread_mutex_unlock(&out->lock);
3106
3107 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003108 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003109 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303110 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303111 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303112 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303113 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303114 out->standby = true;
3115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303117 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3118 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3119 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 }
3121 return bytes;
3122}
3123
3124static int out_get_render_position(const struct audio_stream_out *stream,
3125 uint32_t *dsp_frames)
3126{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303128 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003129
3130 if (dsp_frames == NULL)
3131 return -EINVAL;
3132
3133 *dsp_frames = 0;
3134 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003135 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303136
3137 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3138 * this operation and adev_close_output_stream(where out gets reset).
3139 */
3140 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3141 *dsp_frames = get_actual_pcm_frames_rendered(out);
3142 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3143 return 0;
3144 }
3145
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003146 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303147 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303148 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303150 if (ret < 0)
3151 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303153 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154 }
3155 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303156 if (-ENETRESET == ret) {
3157 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3158 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3159 return -EINVAL;
3160 } else if(ret < 0) {
3161 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3162 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303163 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3164 /*
3165 * Handle corner case where compress session is closed during SSR
3166 * and timestamp is queried
3167 */
3168 ALOGE(" ERROR: sound card not active, return error");
3169 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303170 } else {
3171 return 0;
3172 }
Zhou Song32a556e2015-05-05 10:46:56 +08003173 } else if (audio_is_linear_pcm(out->format)) {
3174 *dsp_frames = out->written;
3175 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003176 } else
3177 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178}
3179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003180static int out_add_audio_effect(const struct audio_stream *stream __unused,
3181 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182{
3183 return 0;
3184}
3185
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003186static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3187 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188{
3189 return 0;
3190}
3191
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003192static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3193 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194{
3195 return -EINVAL;
3196}
3197
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003198static int out_get_presentation_position(const struct audio_stream_out *stream,
3199 uint64_t *frames, struct timespec *timestamp)
3200{
3201 struct stream_out *out = (struct stream_out *)stream;
3202 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003203 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003204
Ashish Jain5106d362016-05-11 19:23:33 +05303205 /* below piece of code is not guarded against any lock because audioFliner serializes
3206 * this operation and adev_close_output_stream( where out gets reset).
3207 */
3208 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3209 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3210 *frames = get_actual_pcm_frames_rendered(out);
3211 /* this is the best we can do */
3212 clock_gettime(CLOCK_MONOTONIC, timestamp);
3213 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3214 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3215 return 0;
3216 }
3217
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003218 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003219
Ashish Jain5106d362016-05-11 19:23:33 +05303220 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3221 ret = compress_get_tstamp(out->compr, &dsp_frames,
3222 &out->sample_rate);
3223 ALOGVV("%s rendered frames %ld sample_rate %d",
3224 __func__, dsp_frames, out->sample_rate);
3225 *frames = dsp_frames;
3226 if (ret < 0)
3227 ret = -errno;
3228 if (-ENETRESET == ret) {
3229 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3230 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3231 ret = -EINVAL;
3232 } else
3233 ret = 0;
3234 /* this is the best we can do */
3235 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003236 } else {
3237 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003238 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003239 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3240 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003241 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003242 // This adjustment accounts for buffering after app processor.
3243 // It is based on estimated DSP latency per use case, rather than exact.
3244 signed_frames -=
3245 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3246
Eric Laurent949a0892013-09-20 09:20:13 -07003247 // It would be unusual for this value to be negative, but check just in case ...
3248 if (signed_frames >= 0) {
3249 *frames = signed_frames;
3250 ret = 0;
3251 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003252 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303253 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3254 *frames = out->written;
3255 clock_gettime(CLOCK_MONOTONIC, timestamp);
3256 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003257 }
3258 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003259 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003260 return ret;
3261}
3262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263static int out_set_callback(struct audio_stream_out *stream,
3264 stream_callback_t callback, void *cookie)
3265{
3266 struct stream_out *out = (struct stream_out *)stream;
3267
3268 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003269 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 out->offload_callback = callback;
3271 out->offload_cookie = cookie;
3272 pthread_mutex_unlock(&out->lock);
3273 return 0;
3274}
3275
3276static int out_pause(struct audio_stream_out* stream)
3277{
3278 struct stream_out *out = (struct stream_out *)stream;
3279 int status = -ENOSYS;
3280 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003281 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003282 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003283 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303285 struct audio_device *adev = out->dev;
3286 int snd_scard_state = get_snd_card_state(adev);
3287
3288 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3289 status = compress_pause(out->compr);
3290
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003291 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003292
Mingming Yin21854652016-04-13 11:54:02 -07003293 if (audio_extn_passthru_is_active()) {
3294 ALOGV("offload use case, pause passthru");
3295 audio_extn_passthru_on_pause(out);
3296 }
3297
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303298 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003299 audio_extn_dts_notify_playback_state(out->usecase, 0,
3300 out->sample_rate, popcount(out->channel_mask),
3301 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003302 }
3303 pthread_mutex_unlock(&out->lock);
3304 }
3305 return status;
3306}
3307
3308static int out_resume(struct audio_stream_out* stream)
3309{
3310 struct stream_out *out = (struct stream_out *)stream;
3311 int status = -ENOSYS;
3312 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003313 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003314 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003315 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003316 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003317 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303318 struct audio_device *adev = out->dev;
3319 int snd_scard_state = get_snd_card_state(adev);
3320
Mingming Yin21854652016-04-13 11:54:02 -07003321 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3322 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3323 pthread_mutex_lock(&out->dev->lock);
3324 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003325 pthread_mutex_unlock(&out->dev->lock);
3326 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303327 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003328 }
3329 if (!status) {
3330 out->offload_state = OFFLOAD_STATE_PLAYING;
3331 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303332 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003333 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3334 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 }
3336 pthread_mutex_unlock(&out->lock);
3337 }
3338 return status;
3339}
3340
3341static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3342{
3343 struct stream_out *out = (struct stream_out *)stream;
3344 int status = -ENOSYS;
3345 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003346 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003347 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3349 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3350 else
3351 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3352 pthread_mutex_unlock(&out->lock);
3353 }
3354 return status;
3355}
3356
3357static int out_flush(struct audio_stream_out* stream)
3358{
3359 struct stream_out *out = (struct stream_out *)stream;
3360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003362 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003363 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003364 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3365 stop_compressed_output_l(out);
3366 out->written = 0;
3367 } else {
3368 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3369 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003371 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 return 0;
3373 }
3374 return -ENOSYS;
3375}
3376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377/** audio_stream_in implementation **/
3378static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3379{
3380 struct stream_in *in = (struct stream_in *)stream;
3381
3382 return in->config.rate;
3383}
3384
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003385static int in_set_sample_rate(struct audio_stream *stream __unused,
3386 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387{
3388 return -ENOSYS;
3389}
3390
3391static size_t in_get_buffer_size(const struct audio_stream *stream)
3392{
3393 struct stream_in *in = (struct stream_in *)stream;
3394
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003395 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3396 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003397 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3398 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003399
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003400 return in->config.period_size * in->af_period_multiplier *
3401 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402}
3403
3404static uint32_t in_get_channels(const struct audio_stream *stream)
3405{
3406 struct stream_in *in = (struct stream_in *)stream;
3407
3408 return in->channel_mask;
3409}
3410
3411static audio_format_t in_get_format(const struct audio_stream *stream)
3412{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003413 struct stream_in *in = (struct stream_in *)stream;
3414
3415 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416}
3417
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003418static int in_set_format(struct audio_stream *stream __unused,
3419 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420{
3421 return -ENOSYS;
3422}
3423
3424static int in_standby(struct audio_stream *stream)
3425{
3426 struct stream_in *in = (struct stream_in *)stream;
3427 struct audio_device *adev = in->dev;
3428 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303429 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3430 stream, in->usecase, use_case_table[in->usecase]);
3431
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003432 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003433 if (!in->standby && in->is_st_session) {
3434 ALOGD("%s: sound trigger pcm stop lab", __func__);
3435 audio_extn_sound_trigger_stop_lab(in);
3436 in->standby = 1;
3437 }
3438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003440 if (adev->adm_deregister_stream)
3441 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3442
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003443 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003445 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3446 voice_extn_compress_voip_close_input_stream(stream);
3447 ALOGD("VOIP input entered standby");
3448 } else {
3449 if (in->pcm) {
3450 pcm_close(in->pcm);
3451 in->pcm = NULL;
3452 }
3453 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003454 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003455 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 }
3457 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003458 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 return status;
3460}
3461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003462static int in_dump(const struct audio_stream *stream __unused,
3463 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464{
3465 return 0;
3466}
3467
3468static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3469{
3470 struct stream_in *in = (struct stream_in *)stream;
3471 struct audio_device *adev = in->dev;
3472 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003474 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303476 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 parms = str_parms_create_str(kvpairs);
3478
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303479 if (!parms)
3480 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003481 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003482 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003483
3484 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3485 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 val = atoi(value);
3487 /* no audio source uses val == 0 */
3488 if ((in->source != val) && (val != 0)) {
3489 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003490 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3491 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3492 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003493 (in->config.rate == 8000 || in->config.rate == 16000 ||
3494 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003495 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003496 err = voice_extn_compress_voip_open_input_stream(in);
3497 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003498 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003499 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003500 }
3501 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 }
3503 }
3504
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003505 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3506 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003508 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 in->device = val;
3510 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003511 if (!in->standby && !in->is_st_session) {
3512 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003513 if (adev->adm_on_routing_change)
3514 adev->adm_on_routing_change(adev->adm_data,
3515 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003516 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 }
3519 }
3520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
3524 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303525error:
Eric Laurent994a6932013-07-17 11:51:42 -07003526 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 return ret;
3528}
3529
3530static char* in_get_parameters(const struct audio_stream *stream,
3531 const char *keys)
3532{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003533 struct stream_in *in = (struct stream_in *)stream;
3534 struct str_parms *query = str_parms_create_str(keys);
3535 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003536 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003537
3538 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003539 if (reply) {
3540 str_parms_destroy(reply);
3541 }
3542 if (query) {
3543 str_parms_destroy(query);
3544 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003545 ALOGE("in_get_parameters: failed to create query or reply");
3546 return NULL;
3547 }
3548
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 ALOGV("%s: enter: keys - %s", __func__, keys);
3550
3551 voice_extn_in_get_parameters(in, query, reply);
3552
3553 str = str_parms_to_str(reply);
3554 str_parms_destroy(query);
3555 str_parms_destroy(reply);
3556
3557 ALOGV("%s: exit: returns - %s", __func__, str);
3558 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559}
3560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003561static int in_set_gain(struct audio_stream_in *stream __unused,
3562 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
3564 return 0;
3565}
3566
3567static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3568 size_t bytes)
3569{
3570 struct stream_in *in = (struct stream_in *)stream;
3571 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303572 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303573 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303574 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003576 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303577
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003578 if (in->is_st_session) {
3579 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3580 /* Read from sound trigger HAL */
3581 audio_extn_sound_trigger_read(in, buffer, bytes);
3582 pthread_mutex_unlock(&in->lock);
3583 return bytes;
3584 }
3585
Ashish Jainbbce4322016-02-16 13:25:27 +05303586 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003587 ALOGD(" %s: sound card is not active/SSR state", __func__);
3588 ret= -EIO;;
3589 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303590 }
3591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003593 pthread_mutex_lock(&adev->lock);
3594 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3595 ret = voice_extn_compress_voip_start_input_stream(in);
3596 else
3597 ret = start_input_stream(in);
3598 pthread_mutex_unlock(&adev->lock);
3599 if (ret != 0) {
3600 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 }
3602 in->standby = 0;
3603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003605 // what's the duration requested by the client?
3606 long ns = 0;
3607
3608 if (in->config.rate)
3609 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3610 in->config.rate;
3611
3612 request_in_focus(in, ns);
3613 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303616 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003617 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303618 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003619 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003620 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003621 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303622 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003623 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303624 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3625 if (bytes % 4 == 0) {
3626 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3627 int_buf_stream = buffer;
Yamit Mehtaa0d653a2016-11-25 20:33:25 +05303628 size_t itt = 0;
3629 for (itt = 0; itt < bytes/4 ; itt++) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303630 int_buf_stream[itt] >>= 8;
3631 }
3632 } else {
3633 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3634 ret = -EINVAL;
3635 goto exit;
3636 }
3637 } if (ret < 0) {
3638 ret = -errno;
3639 }
3640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 }
3642
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003643 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 /*
3646 * Instead of writing zeroes here, we could trust the hardware
3647 * to always provide zeroes when muted.
3648 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303649 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3650 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 memset(buffer, 0, bytes);
3652
3653exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303654 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303655 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003656 if (-ENETRESET == ret)
3657 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 pthread_mutex_unlock(&in->lock);
3660
3661 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303662 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303663 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303664 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303665 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303666 in->standby = true;
3667 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303668 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003670 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303671 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303672 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 }
3674 return bytes;
3675}
3676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003677static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678{
3679 return 0;
3680}
3681
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003682static int add_remove_audio_effect(const struct audio_stream *stream,
3683 effect_handle_t effect,
3684 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003686 struct stream_in *in = (struct stream_in *)stream;
3687 int status = 0;
3688 effect_descriptor_t desc;
3689
3690 status = (*effect)->get_descriptor(effect, &desc);
3691 if (status != 0)
3692 return status;
3693
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003694 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003695 pthread_mutex_lock(&in->dev->lock);
3696 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3697 in->enable_aec != enable &&
3698 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3699 in->enable_aec = enable;
3700 if (!in->standby)
3701 select_devices(in->dev, in->usecase);
3702 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003703 if (in->enable_ns != enable &&
3704 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3705 in->enable_ns = enable;
3706 if (!in->standby)
3707 select_devices(in->dev, in->usecase);
3708 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003709 pthread_mutex_unlock(&in->dev->lock);
3710 pthread_mutex_unlock(&in->lock);
3711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 return 0;
3713}
3714
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003715static int in_add_audio_effect(const struct audio_stream *stream,
3716 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717{
Eric Laurent994a6932013-07-17 11:51:42 -07003718 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003719 return add_remove_audio_effect(stream, effect, true);
3720}
3721
3722static int in_remove_audio_effect(const struct audio_stream *stream,
3723 effect_handle_t effect)
3724{
Eric Laurent994a6932013-07-17 11:51:42 -07003725 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003726 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727}
3728
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303729int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 audio_io_handle_t handle,
3731 audio_devices_t devices,
3732 audio_output_flags_t flags,
3733 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003734 struct audio_stream_out **stream_out,
3735 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736{
3737 struct audio_device *adev = (struct audio_device *)dev;
3738 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303739 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003740 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303743
3744 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3745 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003746 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303747 return -EINVAL;
3748 }
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3751
Mingming Yin3a941d42016-02-17 18:08:05 -08003752 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3753 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303754 devices, flags, &out->stream);
3755
3756
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003757 if (!out) {
3758 return -ENOMEM;
3759 }
3760
Haynes Mathew George204045b2015-02-25 20:32:03 -08003761 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003762 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003763 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 if (devices == AUDIO_DEVICE_NONE)
3766 devices = AUDIO_DEVICE_OUT_SPEAKER;
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 out->flags = flags;
3769 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003770 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003771 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772 out->sample_rate = config->sample_rate;
3773 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3774 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003775 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003776 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003777 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303778 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779
Mingming Yin3a941d42016-02-17 18:08:05 -08003780 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3781 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3782 pthread_mutex_lock(&adev->lock);
3783 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3784 ret = read_hdmi_sink_caps(out);
3785 pthread_mutex_unlock(&adev->lock);
3786 if (ret != 0) {
3787 if (ret == -ENOSYS) {
3788 /* ignore and go with default */
3789 ret = 0;
3790 } else {
3791 ALOGE("error reading hdmi sink caps");
3792 goto error_open;
3793 }
3794 }
3795 }
3796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003798 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303799 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3800 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003801 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3802 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3803
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003804 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003805 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3806 /*
3807 * Do not handle stereo output in Multi-channel cases
3808 * Stereo case is handled in normal playback path
3809 */
3810 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3811 ret = AUDIO_CHANNEL_OUT_STEREO;
3812 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003813
3814 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3815 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003816 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003817 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003818 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003819
3820 if (config->sample_rate == 0)
3821 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3822 if (config->channel_mask == 0)
3823 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003824 if (config->format == 0)
3825 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003826
3827 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003828 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003829 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3831 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003833 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003835 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3836 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003837 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003838 ret = voice_extn_compress_voip_open_output_stream(out);
3839 if (ret != 0) {
3840 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3841 __func__, ret);
3842 goto error_open;
3843 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003844 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3845 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003847 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3848 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3849 ALOGE("%s: Unsupported Offload information", __func__);
3850 ret = -EINVAL;
3851 goto error_open;
3852 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003853
Mingming Yin3a941d42016-02-17 18:08:05 -08003854 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003855 if(config->offload_info.format == 0)
3856 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003857 if (config->offload_info.sample_rate == 0)
3858 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003859 }
3860
Mingming Yin90310102013-11-13 16:57:00 -08003861 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303862 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003863 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003864 ret = -EINVAL;
3865 goto error_open;
3866 }
3867
3868 out->compr_config.codec = (struct snd_codec *)
3869 calloc(1, sizeof(struct snd_codec));
3870
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003871 if (!out->compr_config.codec) {
3872 ret = -ENOMEM;
3873 goto error_open;
3874 }
3875
vivek mehta0ea887a2015-08-26 14:01:20 -07003876 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303877 out->stream.pause = out_pause;
3878 out->stream.flush = out_flush;
3879 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003880 out->usecase = get_offload_usecase(adev, true);
3881 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003882 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003883 out->stream.set_callback = out_set_callback;
3884 out->stream.pause = out_pause;
3885 out->stream.resume = out_resume;
3886 out->stream.drain = out_drain;
3887 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003888 out->usecase = get_offload_usecase(adev, false);
3889 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003890 }
vivek mehta446c3962015-09-14 10:57:35 -07003891
3892 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003893 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3894 config->format == 0 && config->sample_rate == 0 &&
3895 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003896 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003897 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3898 } else {
3899 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3900 ret = -EEXIST;
3901 goto error_open;
3902 }
vivek mehta446c3962015-09-14 10:57:35 -07003903 }
3904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003905 if (config->offload_info.channel_mask)
3906 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003907 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003908 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003909 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003910 } else {
3911 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3912 ret = -EINVAL;
3913 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003914 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003915
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003916 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003917 out->sample_rate = config->offload_info.sample_rate;
3918
Mingming Yin3ee55c62014-08-04 14:23:35 -07003919 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303921 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3922 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3923 audio_extn_dolby_send_ddp_endp_params(adev);
3924 audio_extn_dolby_set_dmid(adev);
3925 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003927 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003928 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929 out->compr_config.codec->bit_rate =
3930 config->offload_info.bit_rate;
3931 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303932 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003933 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303934 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003935 /*TODO: Do we need to change it for passthrough */
3936 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937
Manish Dewangana6fc5442015-08-24 20:30:31 +05303938 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3939 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3940 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3941 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303942
3943 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3944 AUDIO_FORMAT_PCM) {
3945
3946 /*Based on platform support, configure appropriate alsa format for corresponding
3947 *hal input format.
3948 */
3949 out->compr_config.codec->format = hal_format_to_alsa(
3950 config->offload_info.format);
3951
Ashish Jain83a6cc22016-06-28 14:34:17 +05303952 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303953 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303954 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303955
3956 /*for direct PCM playback populate bit_width based on selected alsa format as
3957 *hal input format and alsa format might differ based on platform support.
3958 */
3959 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303960 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303961
3962 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3963
3964 /* Check if alsa session is configured with the same format as HAL input format,
3965 * if not then derive correct fragment size needed to accomodate the
3966 * conversion of HAL input format to alsa format.
3967 */
3968 audio_extn_utils_update_direct_pcm_fragment_size(out);
3969
3970 /*if hal input and output fragment size is different this indicates HAL input format is
3971 *not same as the alsa format
3972 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303973 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303974 /*Allocate a buffer to convert input data to the alsa configured format.
3975 *size of convert buffer is equal to the size required to hold one fragment size
3976 *worth of pcm data, this is because flinger does not write more than fragment_size
3977 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303978 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3979 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303980 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3981 ret = -ENOMEM;
3982 goto error_open;
3983 }
3984 }
3985 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3986 out->compr_config.fragment_size =
3987 audio_extn_passthru_get_buffer_size(&config->offload_info);
3988 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3989 } else {
3990 out->compr_config.fragment_size =
3991 platform_get_compress_offload_buffer_size(&config->offload_info);
3992 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3993 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003994
Amit Shekhar6f461b12014-08-01 14:52:58 -07003995 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303996 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003997
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003998 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3999 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004000
Alexy Josephaa54c872014-12-03 02:46:47 -08004001
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004002 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304003 out->send_next_track_params = false;
4004 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004005 out->offload_state = OFFLOAD_STATE_IDLE;
4006 out->playback_started = 0;
4007
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004008 audio_extn_dts_create_state_notifier_node(out->usecase);
4009
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4011 __func__, config->offload_info.version,
4012 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304013
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304014 /* Check if DSD audio format is supported in codec
4015 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304016 */
4017
4018 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304019 (!platform_check_codec_dsd_support(adev->platform) ||
4020 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304021 ret = -EINVAL;
4022 goto error_open;
4023 }
4024
Ashish Jain5106d362016-05-11 19:23:33 +05304025 /* Disable gapless if any of the following is true
4026 * passthrough playback
4027 * AV playback
4028 * Direct PCM playback
4029 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304030 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304031 (config->format == AUDIO_FORMAT_DSD) ||
4032 config->offload_info.has_video ||
4033 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304034 check_and_set_gapless_mode(adev, false);
4035 } else
4036 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004037
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304038 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004039 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4040 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304041 if (config->format == AUDIO_FORMAT_DSD) {
4042 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4043 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4044 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004045
4046 create_offload_callback_thread(out);
4047
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004048 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304049 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004050 if (ret != 0) {
4051 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4052 __func__, ret);
4053 goto error_open;
4054 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004055 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4056 if (config->sample_rate == 0)
4057 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4058 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4059 config->sample_rate != 8000) {
4060 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4061 ret = -EINVAL;
4062 goto error_open;
4063 }
4064 out->sample_rate = config->sample_rate;
4065 out->config.rate = config->sample_rate;
4066 if (config->format == AUDIO_FORMAT_DEFAULT)
4067 config->format = AUDIO_FORMAT_PCM_16_BIT;
4068 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4069 config->format = AUDIO_FORMAT_PCM_16_BIT;
4070 ret = -EINVAL;
4071 goto error_open;
4072 }
4073 out->format = config->format;
4074 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4075 out->config = pcm_config_afe_proxy_playback;
4076 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004077 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304078 unsigned int channels = 0;
4079 /*Update config params to default if not set by the caller*/
4080 if (config->sample_rate == 0)
4081 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4082 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4083 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4084 if (config->format == AUDIO_FORMAT_DEFAULT)
4085 config->format = AUDIO_FORMAT_PCM_16_BIT;
4086
4087 channels = audio_channel_count_from_out_mask(out->channel_mask);
4088
Ashish Jain83a6cc22016-06-28 14:34:17 +05304089 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4090 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004091 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4092 out->flags);
4093 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304094 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4095 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4096 out->config = pcm_config_low_latency;
4097 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4098 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4099 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304100 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4101 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4102 if (out->config.period_size <= 0) {
4103 ALOGE("Invalid configuration period size is not valid");
4104 ret = -EINVAL;
4105 goto error_open;
4106 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304107 } else {
4108 /* primary path is the default path selected if no other outputs are available/suitable */
4109 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4110 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4111 }
4112 out->hal_ip_format = format = out->format;
4113 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4114 out->hal_op_format = pcm_format_to_hal(out->config.format);
4115 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4116 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004117 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304118 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304119 if (out->hal_ip_format != out->hal_op_format) {
4120 uint32_t buffer_size = out->config.period_size *
4121 format_to_bitwidth_table[out->hal_op_format] *
4122 out->config.channels;
4123 out->convert_buffer = calloc(1, buffer_size);
4124 if (out->convert_buffer == NULL){
4125 ALOGE("Allocation failed for convert buffer for size %d",
4126 out->compr_config.fragment_size);
4127 ret = -ENOMEM;
4128 goto error_open;
4129 }
4130 ALOGD("Convert buffer allocated of size %d", buffer_size);
4131 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 }
4133
Ashish Jain83a6cc22016-06-28 14:34:17 +05304134 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4135 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4136
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004137 /* TODO remove this hardcoding and check why width is zero*/
4138 if (out->bit_width == 0)
4139 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004140 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
4141 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004142 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05304143 out->bit_width, out->channel_mask,
4144 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004145 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4146 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4147 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004148 if(adev->primary_output == NULL)
4149 adev->primary_output = out;
4150 else {
4151 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004152 ret = -EEXIST;
4153 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004154 }
4155 }
4156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 /* Check if this usecase is already existing */
4158 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004159 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4160 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004163 ret = -EEXIST;
4164 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 }
4166 pthread_mutex_unlock(&adev->lock);
4167
4168 out->stream.common.get_sample_rate = out_get_sample_rate;
4169 out->stream.common.set_sample_rate = out_set_sample_rate;
4170 out->stream.common.get_buffer_size = out_get_buffer_size;
4171 out->stream.common.get_channels = out_get_channels;
4172 out->stream.common.get_format = out_get_format;
4173 out->stream.common.set_format = out_set_format;
4174 out->stream.common.standby = out_standby;
4175 out->stream.common.dump = out_dump;
4176 out->stream.common.set_parameters = out_set_parameters;
4177 out->stream.common.get_parameters = out_get_parameters;
4178 out->stream.common.add_audio_effect = out_add_audio_effect;
4179 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4180 out->stream.get_latency = out_get_latency;
4181 out->stream.set_volume = out_set_volume;
4182 out->stream.write = out_write;
4183 out->stream.get_render_position = out_get_render_position;
4184 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004185 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004187 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004189 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004190 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191
4192 config->format = out->stream.common.get_format(&out->stream.common);
4193 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4194 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4195
4196 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304197 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004198 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004199
4200 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4201 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4202 popcount(out->channel_mask), out->playback_started);
4203
Eric Laurent994a6932013-07-17 11:51:42 -07004204 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004206
4207error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304208 if (out->convert_buffer)
4209 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004210 free(out);
4211 *stream_out = NULL;
4212 ALOGD("%s: exit: ret %d", __func__, ret);
4213 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214}
4215
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304216void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 struct audio_stream_out *stream)
4218{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004219 struct stream_out *out = (struct stream_out *)stream;
4220 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004221 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004222
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304223 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4224
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004225 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304226 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004227 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304228 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004229 if(ret != 0)
4230 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4231 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004232 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004233 out_standby(&stream->common);
4234
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004235 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004236 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004237 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004238 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004239 if (out->compr_config.codec != NULL)
4240 free(out->compr_config.codec);
4241 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004242
Ashish Jain83a6cc22016-06-28 14:34:17 +05304243 if (out->convert_buffer != NULL) {
4244 free(out->convert_buffer);
4245 out->convert_buffer = NULL;
4246 }
4247
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004248 if (adev->voice_tx_output == out)
4249 adev->voice_tx_output = NULL;
4250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004251 pthread_cond_destroy(&out->cond);
4252 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004254 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255}
4256
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004257static void close_compress_sessions(struct audio_device *adev)
4258{
Mingming Yin7b762e72015-03-04 13:47:32 -08004259 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304260 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004261 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004262 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304263
4264 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004265 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304266 if (is_offload_usecase(usecase->id)) {
4267 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004268 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4269 out = usecase->stream.out;
4270 pthread_mutex_unlock(&adev->lock);
4271 out_standby(&out->stream.common);
4272 pthread_mutex_lock(&adev->lock);
4273 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304274 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004275 }
4276 pthread_mutex_unlock(&adev->lock);
4277}
4278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4280{
4281 struct audio_device *adev = (struct audio_device *)dev;
4282 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004284 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004285 int ret;
4286 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004288 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304291 if (!parms)
4292 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004293 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4294 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304295 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304296 if (strstr(snd_card_status, "OFFLINE")) {
4297 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304298 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004299 //close compress sessions on OFFLINE status
4300 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304301 } else if (strstr(snd_card_status, "ONLINE")) {
4302 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304303 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004304 //send dts hpx license if enabled
4305 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304306 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304307 }
4308
4309 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004310 status = voice_set_parameters(adev, parms);
4311 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004312 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004314 status = platform_set_parameters(adev->platform, parms);
4315 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004316 goto done;
4317
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004318 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4319 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004320 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4322 adev->bluetooth_nrec = true;
4323 else
4324 adev->bluetooth_nrec = false;
4325 }
4326
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004327 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4328 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4330 adev->screen_off = false;
4331 else
4332 adev->screen_off = true;
4333 }
4334
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004335 ret = str_parms_get_int(parms, "rotation", &val);
4336 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004337 bool reverse_speakers = false;
4338 switch(val) {
4339 // FIXME: note that the code below assumes that the speakers are in the correct placement
4340 // relative to the user when the device is rotated 90deg from its default rotation. This
4341 // assumption is device-specific, not platform-specific like this code.
4342 case 270:
4343 reverse_speakers = true;
4344 break;
4345 case 0:
4346 case 90:
4347 case 180:
4348 break;
4349 default:
4350 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004351 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004352 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004353 if (status == 0) {
4354 if (adev->speaker_lr_swap != reverse_speakers) {
4355 adev->speaker_lr_swap = reverse_speakers;
4356 // only update the selected device if there is active pcm playback
4357 struct audio_usecase *usecase;
4358 struct listnode *node;
4359 list_for_each(node, &adev->usecase_list) {
4360 usecase = node_to_item(node, struct audio_usecase, list);
4361 if (usecase->type == PCM_PLAYBACK) {
4362 select_devices(adev, usecase->id);
4363 break;
4364 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004365 }
4366 }
4367 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004368 }
4369
Mingming Yin514a8bc2014-07-29 15:22:21 -07004370 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4371 if (ret >= 0) {
4372 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4373 adev->bt_wb_speech_enabled = true;
4374 else
4375 adev->bt_wb_speech_enabled = false;
4376 }
4377
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004378 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4379 if (ret >= 0) {
4380 val = atoi(value);
4381 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004382 ALOGV("cache new ext disp type and edid");
4383 ret = platform_get_ext_disp_type(adev->platform);
4384 if (ret < 0) {
4385 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004386 status = ret;
4387 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004388 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004389 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004390 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004391 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004392 /*
4393 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4394 * Per AudioPolicyManager, USB device is higher priority than WFD.
4395 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4396 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4397 * starting voice call on USB
4398 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004399 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4400 if (ret >= 0) {
4401 audio_extn_usb_add_device(val, atoi(value));
4402 }
vivek mehta344576a2016-04-12 18:56:03 -07004403 ALOGV("detected USB connect .. disable proxy");
4404 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004405 }
4406 }
4407
4408 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4409 if (ret >= 0) {
4410 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004411 /*
4412 * The HDMI / Displayport disconnect handling has been moved to
4413 * audio extension to ensure that its parameters are not
4414 * invalidated prior to updating sysfs of the disconnect event
4415 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4416 */
4417 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004418 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004419 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4420 if (ret >= 0) {
4421 audio_extn_usb_remove_device(val, atoi(value));
4422 }
vivek mehta344576a2016-04-12 18:56:03 -07004423 ALOGV("detected USB disconnect .. enable proxy");
4424 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004425 }
4426 }
4427
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304428 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4429 if (ret >= 0) {
4430 struct audio_usecase *usecase;
4431 struct listnode *node;
4432 list_for_each(node, &adev->usecase_list) {
4433 usecase = node_to_item(node, struct audio_usecase, list);
4434 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004435 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304436 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304437 lock_output_stream(usecase->stream.out);
4438 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304439 //force device switch to re configure encoder
4440 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304441 audio_extn_a2dp_set_handoff_mode(false);
4442 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304443 break;
4444 }
4445 }
4446 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304447 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004448done:
4449 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004450 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304451error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004452 ALOGV("%s: exit with code(%d)", __func__, status);
4453 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454}
4455
4456static char* adev_get_parameters(const struct audio_hw_device *dev,
4457 const char *keys)
4458{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004459 struct audio_device *adev = (struct audio_device *)dev;
4460 struct str_parms *reply = str_parms_create();
4461 struct str_parms *query = str_parms_create_str(keys);
4462 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304463 char value[256] = {0};
4464 int ret = 0;
4465
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004466 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004467 if (reply) {
4468 str_parms_destroy(reply);
4469 }
4470 if (query) {
4471 str_parms_destroy(query);
4472 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004473 ALOGE("adev_get_parameters: failed to create query or reply");
4474 return NULL;
4475 }
4476
Naresh Tannirud7205b62014-06-20 02:54:48 +05304477 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4478 sizeof(value));
4479 if (ret >=0) {
4480 int val = 1;
4481 pthread_mutex_lock(&adev->snd_card_status.lock);
4482 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4483 val = 0;
4484 pthread_mutex_unlock(&adev->snd_card_status.lock);
4485 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4486 goto exit;
4487 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004488
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004489 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004490 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004491 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004492 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304493 pthread_mutex_unlock(&adev->lock);
4494
Naresh Tannirud7205b62014-06-20 02:54:48 +05304495exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004496 str = str_parms_to_str(reply);
4497 str_parms_destroy(query);
4498 str_parms_destroy(reply);
4499
4500 ALOGV("%s: exit: returns - %s", __func__, str);
4501 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502}
4503
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004504static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004505{
4506 return 0;
4507}
4508
4509static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4510{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004511 int ret;
4512 struct audio_device *adev = (struct audio_device *)dev;
4513 pthread_mutex_lock(&adev->lock);
4514 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004515 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004516 pthread_mutex_unlock(&adev->lock);
4517 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518}
4519
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004520static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4521 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522{
4523 return -ENOSYS;
4524}
4525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004526static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4527 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528{
4529 return -ENOSYS;
4530}
4531
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004532static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4533 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534{
4535 return -ENOSYS;
4536}
4537
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004538static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4539 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540{
4541 return -ENOSYS;
4542}
4543
4544static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4545{
4546 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 pthread_mutex_lock(&adev->lock);
4549 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004550 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004552 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004553 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004554 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004555 adev->current_call_output = NULL;
4556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 }
4558 pthread_mutex_unlock(&adev->lock);
4559 return 0;
4560}
4561
4562static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4563{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004564 int ret;
4565
4566 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004567 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004568 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4569 pthread_mutex_unlock(&adev->lock);
4570
4571 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572}
4573
4574static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4575{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004576 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 return 0;
4578}
4579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004580static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 const struct audio_config *config)
4582{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004583 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004584
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004585 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4586 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587}
4588
4589static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004590 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 audio_devices_t devices,
4592 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004593 struct audio_stream_in **stream_in,
4594 audio_input_flags_t flags __unused,
4595 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004596 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597{
4598 struct audio_device *adev = (struct audio_device *)dev;
4599 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004600 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004601 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004602 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304603 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304606 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4607 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610
4611 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004612
4613 if (!in) {
4614 ALOGE("failed to allocate input stream");
4615 return -ENOMEM;
4616 }
4617
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304618 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304619 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4620 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004621 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004622 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 in->stream.common.get_sample_rate = in_get_sample_rate;
4625 in->stream.common.set_sample_rate = in_set_sample_rate;
4626 in->stream.common.get_buffer_size = in_get_buffer_size;
4627 in->stream.common.get_channels = in_get_channels;
4628 in->stream.common.get_format = in_get_format;
4629 in->stream.common.set_format = in_set_format;
4630 in->stream.common.standby = in_standby;
4631 in->stream.common.dump = in_dump;
4632 in->stream.common.set_parameters = in_set_parameters;
4633 in->stream.common.get_parameters = in_get_parameters;
4634 in->stream.common.add_audio_effect = in_add_audio_effect;
4635 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4636 in->stream.set_gain = in_set_gain;
4637 in->stream.read = in_read;
4638 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4639
4640 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004641 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 in->standby = 1;
4644 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004645 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004646 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647
4648 /* Update config params with the requested sample rate and channels */
4649 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004650 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4651 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4652 is_low_latency = true;
4653#if LOW_LATENCY_CAPTURE_USE_CASE
4654 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4655#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004656 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004657 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004658
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004659 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004660 if (in->realtime) {
4661 in->config = pcm_config_audio_capture_rt;
4662 in->sample_rate = in->config.rate;
4663 in->af_period_multiplier = af_period_multiplier;
4664 } else {
4665 in->config = pcm_config_audio_capture;
4666 in->config.rate = config->sample_rate;
4667 in->sample_rate = config->sample_rate;
4668 in->af_period_multiplier = 1;
4669 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304670 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004672 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304673 if (adev->mode != AUDIO_MODE_IN_CALL) {
4674 ret = -EINVAL;
4675 goto err_open;
4676 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004677 if (config->sample_rate == 0)
4678 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4679 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4680 config->sample_rate != 8000) {
4681 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4682 ret = -EINVAL;
4683 goto err_open;
4684 }
4685 if (config->format == AUDIO_FORMAT_DEFAULT)
4686 config->format = AUDIO_FORMAT_PCM_16_BIT;
4687 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4688 config->format = AUDIO_FORMAT_PCM_16_BIT;
4689 ret = -EINVAL;
4690 goto err_open;
4691 }
4692
4693 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4694 in->config = pcm_config_afe_proxy_record;
4695 in->config.channels = channel_count;
4696 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304697 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304698 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4699 in, config, &channel_mask_updated)) {
4700 if (channel_mask_updated == true) {
4701 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4702 __func__, config->channel_mask);
4703 ret = -EINVAL;
4704 goto err_open;
4705 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304706 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004707 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004708 audio_extn_compr_cap_format_supported(config->format) &&
4709 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004710 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004711 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304712 /* restrict 24 bit capture for unprocessed source only
4713 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4714 */
4715 if (config->format == AUDIO_FORMAT_DEFAULT) {
4716 config->format = AUDIO_FORMAT_PCM_16_BIT;
4717 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4718 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4719 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4720 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4721 bool ret_error = false;
4722 in->bit_width = 24;
4723 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4724 from HAL is 24_packed and 8_24
4725 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4726 24_packed return error indicating supported format is 24_packed
4727 *> In case of any other source requesting 24 bit or float return error
4728 indicating format supported is 16 bit only.
4729
4730 on error flinger will retry with supported format passed
4731 */
4732 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4733 (source != AUDIO_SOURCE_CAMCORDER)) {
4734 config->format = AUDIO_FORMAT_PCM_16_BIT;
4735 if( config->sample_rate > 48000)
4736 config->sample_rate = 48000;
4737 ret_error = true;
4738 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4739 in->config.format = PCM_FORMAT_S24_3LE;
4740 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4741 in->config.format = PCM_FORMAT_S24_LE;
4742 } else {
4743 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4744 ret_error = true;
4745 }
4746
4747 if (ret_error) {
4748 ret = -EINVAL;
4749 goto err_open;
4750 }
4751 }
4752
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004753 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004754 if (!in->realtime) {
4755 in->format = config->format;
4756 frame_size = audio_stream_in_frame_size(&in->stream);
4757 buffer_size = get_input_buffer_size(config->sample_rate,
4758 config->format,
4759 channel_count,
4760 is_low_latency);
4761 in->config.period_size = buffer_size / frame_size;
4762 }
4763
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004764 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4765 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4766 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004767 (in->config.rate == 8000 || in->config.rate == 16000 ||
4768 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004769 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4770 voice_extn_compress_voip_open_input_stream(in);
4771 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004772 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004774 /* This stream could be for sound trigger lab,
4775 get sound trigger pcm if present */
4776 audio_extn_sound_trigger_check_and_get_session(in);
4777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004779 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004780 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781
4782err_open:
4783 free(in);
4784 *stream_in = NULL;
4785 return ret;
4786}
4787
4788static void adev_close_input_stream(struct audio_hw_device *dev,
4789 struct audio_stream_in *stream)
4790{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004791 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004792 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004793 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304794
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304795 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004796
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304797 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004798 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304799
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004800 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304801 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004802 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304803 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004804 if (ret != 0)
4805 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4806 __func__, ret);
4807 } else
4808 in_standby(&stream->common);
4809
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004810 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004811 audio_extn_ssr_deinit();
4812 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004813
Mingming Yine62d7842013-10-25 16:26:03 -07004814 if(audio_extn_compr_cap_enabled() &&
4815 audio_extn_compr_cap_format_supported(in->config.format))
4816 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004817
Mingming Yinfd7607b2016-01-22 12:48:44 -08004818 if (in->is_st_session) {
4819 ALOGV("%s: sound trigger pcm stop lab", __func__);
4820 audio_extn_sound_trigger_stop_lab(in);
4821 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004822 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 return;
4824}
4825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004826static int adev_dump(const audio_hw_device_t *device __unused,
4827 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828{
4829 return 0;
4830}
4831
4832static int adev_close(hw_device_t *device)
4833{
4834 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004835
4836 if (!adev)
4837 return 0;
4838
4839 pthread_mutex_lock(&adev_init_lock);
4840
4841 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004842 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004843 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304844 if (audio_extn_qaf_is_enabled())
4845 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004846 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004847 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004848 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004849 free(adev->snd_dev_ref_cnt);
4850 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004851 if (adev->adm_deinit)
4852 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004853 free(device);
4854 adev = NULL;
4855 }
4856 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858 return 0;
4859}
4860
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004861/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4862 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4863 * just that it _might_ work.
4864 */
4865static int period_size_is_plausible_for_low_latency(int period_size)
4866{
4867 switch (period_size) {
4868 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004869 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004870 case 240:
4871 case 320:
4872 case 480:
4873 return 1;
4874 default:
4875 return 0;
4876 }
4877}
4878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879static int adev_open(const hw_module_t *module, const char *name,
4880 hw_device_t **device)
4881{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304882 int ret;
4883
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004884 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4886
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004887 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004888 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004889 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004890 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004891 ALOGD("%s: returning existing instance of adev", __func__);
4892 ALOGD("%s: exit", __func__);
4893 pthread_mutex_unlock(&adev_init_lock);
4894 return 0;
4895 }
4896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 adev = calloc(1, sizeof(struct audio_device));
4898
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004899 if (!adev) {
4900 pthread_mutex_unlock(&adev_init_lock);
4901 return -ENOMEM;
4902 }
4903
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004904 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4907 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4908 adev->device.common.module = (struct hw_module_t *)module;
4909 adev->device.common.close = adev_close;
4910
4911 adev->device.init_check = adev_init_check;
4912 adev->device.set_voice_volume = adev_set_voice_volume;
4913 adev->device.set_master_volume = adev_set_master_volume;
4914 adev->device.get_master_volume = adev_get_master_volume;
4915 adev->device.set_master_mute = adev_set_master_mute;
4916 adev->device.get_master_mute = adev_get_master_mute;
4917 adev->device.set_mode = adev_set_mode;
4918 adev->device.set_mic_mute = adev_set_mic_mute;
4919 adev->device.get_mic_mute = adev_get_mic_mute;
4920 adev->device.set_parameters = adev_set_parameters;
4921 adev->device.get_parameters = adev_get_parameters;
4922 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4923 adev->device.open_output_stream = adev_open_output_stream;
4924 adev->device.close_output_stream = adev_close_output_stream;
4925 adev->device.open_input_stream = adev_open_input_stream;
4926 adev->device.close_input_stream = adev_close_input_stream;
4927 adev->device.dump = adev_dump;
4928
4929 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004931 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004932 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004935 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004936 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004937 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004938 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004939 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004940 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004941 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004942 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304943 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304944 adev->perf_lock_opts[0] = 0x101;
4945 adev->perf_lock_opts[1] = 0x20E;
4946 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304947
4948 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4949 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004951 adev->platform = platform_init(adev);
4952 if (!adev->platform) {
4953 free(adev->snd_dev_ref_cnt);
4954 free(adev);
4955 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4956 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004957 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304958 pthread_mutex_destroy(&adev->lock);
4959 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004960 return -EINVAL;
4961 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004962
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304963 if (audio_extn_qaf_is_enabled()) {
4964 ret = audio_extn_qaf_init(adev);
4965 if (ret < 0) {
4966 free(adev);
4967 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4968 *device = NULL;
4969 pthread_mutex_unlock(&adev_init_lock);
4970 pthread_mutex_destroy(&adev->lock);
4971 return ret;
4972 }
4973
4974 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4975 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4976 }
4977
Naresh Tanniru4c630392014-05-12 01:05:52 +05304978 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4979
Eric Laurentc4aef752013-09-12 17:45:53 -07004980 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4981 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4982 if (adev->visualizer_lib == NULL) {
4983 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4984 } else {
4985 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4986 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004987 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004988 "visualizer_hal_start_output");
4989 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004990 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004991 "visualizer_hal_stop_output");
4992 }
4993 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004994 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004995 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004996 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004997
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004998 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4999 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5000 if (adev->offload_effects_lib == NULL) {
5001 ALOGE("%s: DLOPEN failed for %s", __func__,
5002 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5003 } else {
5004 ALOGV("%s: DLOPEN successful for %s", __func__,
5005 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5006 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305007 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005008 "offload_effects_bundle_hal_start_output");
5009 adev->offload_effects_stop_output =
5010 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5011 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005012 adev->offload_effects_set_hpx_state =
5013 (int (*)(bool))dlsym(adev->offload_effects_lib,
5014 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305015 adev->offload_effects_get_parameters =
5016 (void (*)(struct str_parms *, struct str_parms *))
5017 dlsym(adev->offload_effects_lib,
5018 "offload_effects_bundle_get_parameters");
5019 adev->offload_effects_set_parameters =
5020 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5021 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005022 }
5023 }
5024
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005025 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5026 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5027 if (adev->adm_lib == NULL) {
5028 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5029 } else {
5030 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5031 adev->adm_init = (adm_init_t)
5032 dlsym(adev->adm_lib, "adm_init");
5033 adev->adm_deinit = (adm_deinit_t)
5034 dlsym(adev->adm_lib, "adm_deinit");
5035 adev->adm_register_input_stream = (adm_register_input_stream_t)
5036 dlsym(adev->adm_lib, "adm_register_input_stream");
5037 adev->adm_register_output_stream = (adm_register_output_stream_t)
5038 dlsym(adev->adm_lib, "adm_register_output_stream");
5039 adev->adm_deregister_stream = (adm_deregister_stream_t)
5040 dlsym(adev->adm_lib, "adm_deregister_stream");
5041 adev->adm_request_focus = (adm_request_focus_t)
5042 dlsym(adev->adm_lib, "adm_request_focus");
5043 adev->adm_abandon_focus = (adm_abandon_focus_t)
5044 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005045 adev->adm_set_config = (adm_set_config_t)
5046 dlsym(adev->adm_lib, "adm_set_config");
5047 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5048 dlsym(adev->adm_lib, "adm_request_focus_v2");
5049 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5050 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5051 adev->adm_on_routing_change = (adm_on_routing_change_t)
5052 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005053 }
5054 }
5055
Mingming Yin514a8bc2014-07-29 15:22:21 -07005056 adev->bt_wb_speech_enabled = false;
5057
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005058 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059 *device = &adev->device.common;
5060
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005061 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
5062 &adev->streams_output_cfg_list);
5063
Kiran Kandi910e1862013-10-29 13:29:42 -07005064 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005065
5066 char value[PROPERTY_VALUE_MAX];
5067 int trial;
5068 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5069 trial = atoi(value);
5070 if (period_size_is_plausible_for_low_latency(trial)) {
5071 pcm_config_low_latency.period_size = trial;
5072 pcm_config_low_latency.start_threshold = trial / 4;
5073 pcm_config_low_latency.avail_min = trial / 4;
5074 configured_low_latency_capture_period_size = trial;
5075 }
5076 }
5077 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5078 trial = atoi(value);
5079 if (period_size_is_plausible_for_low_latency(trial)) {
5080 configured_low_latency_capture_period_size = trial;
5081 }
5082 }
5083
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005084 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5085 af_period_multiplier = atoi(value);
5086 if (af_period_multiplier < 0)
5087 af_period_multiplier = 2;
5088 else if (af_period_multiplier > 4)
5089 af_period_multiplier = 4;
5090
5091 ALOGV("new period_multiplier = %d", af_period_multiplier);
5092 }
5093
vivek mehta446c3962015-09-14 10:57:35 -07005094 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005095 pthread_mutex_unlock(&adev_init_lock);
5096
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005097 if (adev->adm_init)
5098 adev->adm_data = adev->adm_init();
5099
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305100 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005101 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102 return 0;
5103}
5104
5105static struct hw_module_methods_t hal_module_methods = {
5106 .open = adev_open,
5107};
5108
5109struct audio_module HAL_MODULE_INFO_SYM = {
5110 .common = {
5111 .tag = HARDWARE_MODULE_TAG,
5112 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5113 .hal_api_version = HARDWARE_HAL_API_VERSION,
5114 .id = AUDIO_HARDWARE_MODULE_ID,
5115 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005116 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117 .methods = &hal_module_methods,
5118 },
5119};