blob: fa04db94c336ee0ec54f41a9ab7c31b10ab9c294 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700799 } else if (platform_split_snd_device(adev->platform,
800 snd_device,
801 &num_devices,
802 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530803 for (i = 0; i < num_devices; i++) {
804 enable_snd_device(adev, new_snd_devices[i]);
805 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800806 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700807 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530808
809 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
810 (audio_extn_a2dp_start_playback() < 0)) {
811 ALOGE(" fail to configure A2dp control path ");
812 return -EINVAL;
813 }
814
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700815 /* due to the possibility of calibration overwrite between listen
816 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700817 audio_extn_sound_trigger_update_device_status(snd_device,
818 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530819 audio_extn_listen_update_device_status(snd_device,
820 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700821 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700822 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700823 audio_extn_sound_trigger_update_device_status(snd_device,
824 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530825 audio_extn_listen_update_device_status(snd_device,
826 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700827 return -EINVAL;
828 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300829 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700830 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530831
832 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
833 !adev->native_playback_enabled &&
834 audio_is_true_native_stream_active(adev)) {
835 ALOGD("%s: %d: napb: enabling native mode in hardware",
836 __func__, __LINE__);
837 audio_route_apply_and_update_path(adev->audio_route,
838 "true-native-mode");
839 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 return 0;
843}
844
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700845int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700846 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530848 int i, num_devices = 0;
849 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700850 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
851
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800852 if (snd_device < SND_DEVICE_MIN ||
853 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800854 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800855 return -EINVAL;
856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
858 ALOGE("%s: device ref cnt is already 0", __func__);
859 return -EINVAL;
860 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700861
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700863
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700864 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
865 ALOGE("%s: Invalid sound device returned", __func__);
866 return -EINVAL;
867 }
868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700870 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530871
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800872 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
873 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700874 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700875 } else if (platform_split_snd_device(adev->platform,
876 snd_device,
877 &num_devices,
878 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530879 for (i = 0; i < num_devices; i++) {
880 disable_snd_device(adev, new_snd_devices[i]);
881 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300882 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700883 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300884 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700885
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530886 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
887 audio_extn_a2dp_stop_playback();
888
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700889 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530890 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530891 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
892 adev->native_playback_enabled) {
893 ALOGD("%s: %d: napb: disabling native mode in hardware",
894 __func__, __LINE__);
895 audio_route_reset_and_update_path(adev->audio_route,
896 "true-native-mode");
897 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530898 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
899 adev->asrc_mode_enabled) {
900 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530901 disable_asrc_mode(adev);
902 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530903 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530904
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200905 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700906 audio_extn_sound_trigger_update_device_status(snd_device,
907 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530908 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800909 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800912 return 0;
913}
914
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700915/*
916 legend:
917 uc - existing usecase
918 new_uc - new usecase
919 d1, d11, d2 - SND_DEVICE enums
920 a1, a2 - corresponding ANDROID device enums
921 B1, B2 - backend strings
922
923case 1
924 uc->dev d1 (a1) B1
925 new_uc->dev d1 (a1), d2 (a2) B1, B2
926
927 resolution: disable and enable uc->dev on d1
928
929case 2
930 uc->dev d1 (a1) B1
931 new_uc->dev d11 (a1) B1
932
933 resolution: need to switch uc since d1 and d11 are related
934 (e.g. speaker and voice-speaker)
935 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
936
937case 3
938 uc->dev d1 (a1) B1
939 new_uc->dev d2 (a2) B2
940
941 resolution: no need to switch uc
942
943case 4
944 uc->dev d1 (a1) B1
945 new_uc->dev d2 (a2) B1
946
947 resolution: disable enable uc-dev on d2 since backends match
948 we cannot enable two streams on two different devices if they
949 share the same backend. e.g. if offload is on speaker device using
950 QUAD_MI2S backend and a low-latency stream is started on voice-handset
951 using the same backend, offload must also be switched to voice-handset.
952
953case 5
954 uc->dev d1 (a1) B1
955 new_uc->dev d1 (a1), d2 (a2) B1
956
957 resolution: disable enable uc-dev on d2 since backends match
958 we cannot enable two streams on two different devices if they
959 share the same backend.
960
961case 6
962 uc->dev d1 (a1) B1
963 new_uc->dev d2 (a1) B2
964
965 resolution: no need to switch
966
967case 7
968 uc->dev d1 (a1), d2 (a2) B1, B2
969 new_uc->dev d1 (a1) B1
970
971 resolution: no need to switch
972
973*/
974static snd_device_t derive_playback_snd_device(void * platform,
975 struct audio_usecase *uc,
976 struct audio_usecase *new_uc,
977 snd_device_t new_snd_device)
978{
979 audio_devices_t a1 = uc->stream.out->devices;
980 audio_devices_t a2 = new_uc->stream.out->devices;
981
982 snd_device_t d1 = uc->out_snd_device;
983 snd_device_t d2 = new_snd_device;
984
985 // Treat as a special case when a1 and a2 are not disjoint
986 if ((a1 != a2) && (a1 & a2)) {
987 snd_device_t d3[2];
988 int num_devices = 0;
989 int ret = platform_split_snd_device(platform,
990 popcount(a1) > 1 ? d1 : d2,
991 &num_devices,
992 d3);
993 if (ret < 0) {
994 if (ret != -ENOSYS) {
995 ALOGW("%s failed to split snd_device %d",
996 __func__,
997 popcount(a1) > 1 ? d1 : d2);
998 }
999 goto end;
1000 }
1001
1002 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1003 // But if it does happen, we need to give priority to d2 if
1004 // the combo devices active on the existing usecase share a backend.
1005 // This is because we cannot have a usecase active on a combo device
1006 // and a new usecase requests one device in this combo pair.
1007 if (platform_check_backends_match(d3[0], d3[1])) {
1008 return d2; // case 5
1009 } else {
1010 return d1; // case 1
1011 }
1012 } else {
1013 if (platform_check_backends_match(d1, d2)) {
1014 return d2; // case 2, 4
1015 } else {
1016 return d1; // case 6, 3
1017 }
1018 }
1019
1020end:
1021 return d2; // return whatever was calculated before.
1022}
1023
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301025 struct audio_usecase *uc_info,
1026 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027{
1028 struct listnode *node;
1029 struct audio_usecase *usecase;
1030 bool switch_device[AUDIO_USECASE_MAX];
1031 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301032 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 /*
1034 * This function is to make sure that all the usecases that are active on
1035 * the hardware codec backend are always routed to any one device that is
1036 * handled by the hardware codec.
1037 * For example, if low-latency and deep-buffer usecases are currently active
1038 * on speaker and out_set_parameters(headset) is received on low-latency
1039 * output, then we have to make sure deep-buffer is also switched to headset,
1040 * because of the limitation that both the devices cannot be enabled
1041 * at the same time as they share the same backend.
1042 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001043 /*
1044 * This call is to check if we need to force routing for a particular stream
1045 * If there is a backend configuration change for the device when a
1046 * new stream starts, then ADM needs to be closed and re-opened with the new
1047 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001048 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001049 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001050 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1051 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301052 /* For a2dp device reconfigure all active sessions
1053 * with new AFE encoder format based on a2dp state
1054 */
1055 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1056 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1057 audio_extn_a2dp_is_force_device_switch()) {
1058 force_routing = true;
1059 force_restart_session = true;
1060 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301061 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001063 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001064 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001065 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1067 switch_device[i] = false;
1068
1069 list_for_each(node, &adev->usecase_list) {
1070 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001071
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301072 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1073 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301074 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301075 platform_get_snd_device_name(usecase->out_snd_device),
1076 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001077 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301078 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001079 (derive_playback_snd_device(adev->platform,
1080 usecase, uc_info,
1081 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301082 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1083 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301084 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301085 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301086 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1087
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1089 __func__, use_case_table[usecase->id],
1090 platform_get_snd_device_name(usecase->out_snd_device));
1091 disable_audio_route(adev, usecase);
1092 switch_device[usecase->id] = true;
1093 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 }
1095 }
1096
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301097 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1098 num_uc_to_switch);
1099
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001101 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301103 /* Make sure the previous devices to be disabled first and then enable the
1104 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 list_for_each(node, &adev->usecase_list) {
1106 usecase = node_to_item(node, struct audio_usecase, list);
1107 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001108 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 }
1110 }
1111
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001112 list_for_each(node, &adev->usecase_list) {
1113 usecase = node_to_item(node, struct audio_usecase, list);
1114 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001115 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001116 }
1117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 /* Re-route all the usecases on the shared backend other than the
1120 specified usecase to new snd devices */
1121 list_for_each(node, &adev->usecase_list) {
1122 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301123 /* Update the out_snd_device only before enabling the audio route */
1124 if (switch_device[usecase->id]) {
1125 usecase->out_snd_device = snd_device;
1126 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301127 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301128 use_case_table[usecase->id],
1129 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301130 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 }
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 }
1135}
1136
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301137static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001138 struct audio_usecase *uc_info,
1139 snd_device_t snd_device)
1140{
1141 struct listnode *node;
1142 struct audio_usecase *usecase;
1143 bool switch_device[AUDIO_USECASE_MAX];
1144 int i, num_uc_to_switch = 0;
1145
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301146 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1147 snd_device);
1148 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001149 /*
1150 * This function is to make sure that all the active capture usecases
1151 * are always routed to the same input sound device.
1152 * For example, if audio-record and voice-call usecases are currently
1153 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1154 * is received for voice call then we have to make sure that audio-record
1155 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1156 * because of the limitation that two devices cannot be enabled
1157 * at the same time if they share the same backend.
1158 */
1159 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1160 switch_device[i] = false;
1161
1162 list_for_each(node, &adev->usecase_list) {
1163 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001164 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301166 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001167 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301168 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001169 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001170 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001171 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1172 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001173 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001174 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175 switch_device[usecase->id] = true;
1176 num_uc_to_switch++;
1177 }
1178 }
1179
1180 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001181 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301183 /* Make sure the previous devices to be disabled first and then enable the
1184 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
1187 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001188 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001189 }
1190 }
1191
1192 list_for_each(node, &adev->usecase_list) {
1193 usecase = node_to_item(node, struct audio_usecase, list);
1194 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001195 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196 }
1197 }
1198
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001199 /* Re-route all the usecases on the shared backend other than the
1200 specified usecase to new snd devices */
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 /* Update the in_snd_device only before enabling the audio route */
1204 if (switch_device[usecase->id] ) {
1205 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001206 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301207 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001208 }
1209 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 }
1211}
1212
Mingming Yin3a941d42016-02-17 18:08:05 -08001213static void reset_hdmi_sink_caps(struct stream_out *out) {
1214 int i = 0;
1215
1216 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1217 out->supported_channel_masks[i] = 0;
1218 }
1219 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1220 out->supported_formats[i] = 0;
1221 }
1222 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1223 out->supported_sample_rates[i] = 0;
1224 }
1225}
1226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001228static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229{
Mingming Yin3a941d42016-02-17 18:08:05 -08001230 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001231 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Mingming Yin3a941d42016-02-17 18:08:05 -08001233 reset_hdmi_sink_caps(out);
1234
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001235 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001236 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001237 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001238 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001239 }
1240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001243 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001244 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001245 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1246 case 6:
1247 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1249 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1250 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1252 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 break;
1254 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001255 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001256 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001257 break;
1258 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001259
1260 // check channel format caps
1261 i = 0;
1262 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1263 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1264 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1265 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1266 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1267 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1268 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1269 }
1270
1271 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1272 ALOGV(":%s HDMI supports DTS format", __func__);
1273 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1274 }
1275
1276 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1277 ALOGV(":%s HDMI supports DTS HD format", __func__);
1278 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1279 }
1280
1281
1282 // check sample rate caps
1283 i = 0;
1284 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1285 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1286 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1287 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1288 }
1289 }
1290
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001291 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292}
1293
Alexy Josephb1379942016-01-29 15:49:38 -08001294audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001295 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001296{
1297 struct audio_usecase *usecase;
1298 struct listnode *node;
1299
1300 list_for_each(node, &adev->usecase_list) {
1301 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001302 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001303 ALOGV("%s: usecase id %d", __func__, usecase->id);
1304 return usecase->id;
1305 }
1306 }
1307 return USECASE_INVALID;
1308}
1309
Alexy Josephb1379942016-01-29 15:49:38 -08001310struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001311 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312{
1313 struct audio_usecase *usecase;
1314 struct listnode *node;
1315
1316 list_for_each(node, &adev->usecase_list) {
1317 usecase = node_to_item(node, struct audio_usecase, list);
1318 if (usecase->id == uc_id)
1319 return usecase;
1320 }
1321 return NULL;
1322}
1323
Dhananjay Kumard4833242016-10-06 22:09:12 +05301324struct stream_in *get_next_active_input(const struct audio_device *adev)
1325{
1326 struct audio_usecase *usecase;
1327 struct listnode *node;
1328
1329 list_for_each_reverse(node, &adev->usecase_list) {
1330 usecase = node_to_item(node, struct audio_usecase, list);
1331 if (usecase->type == PCM_CAPTURE)
1332 return usecase->stream.in;
1333 }
1334 return NULL;
1335}
1336
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301337/*
1338 * is a true native playback active
1339 */
1340bool audio_is_true_native_stream_active(struct audio_device *adev)
1341{
1342 bool active = false;
1343 int i = 0;
1344 struct listnode *node;
1345
1346 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1347 ALOGV("%s:napb: not in true mode or non hdphones device",
1348 __func__);
1349 active = false;
1350 goto exit;
1351 }
1352
1353 list_for_each(node, &adev->usecase_list) {
1354 struct audio_usecase *uc;
1355 uc = node_to_item(node, struct audio_usecase, list);
1356 struct stream_out *curr_out =
1357 (struct stream_out*) uc->stream.out;
1358
1359 if (curr_out && PCM_PLAYBACK == uc->type) {
1360 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1361 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1362 uc->id, curr_out->sample_rate,
1363 curr_out->bit_width,
1364 platform_get_snd_device_name(uc->out_snd_device));
1365
1366 if (is_offload_usecase(uc->id) &&
1367 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1368 active = true;
1369 ALOGD("%s:napb:native stream detected", __func__);
1370 }
1371 }
1372 }
1373exit:
1374 return active;
1375}
1376
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301377/*
1378 * if native DSD playback active
1379 */
1380bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1381{
1382 bool active = false;
1383 struct listnode *node = NULL;
1384 struct audio_usecase *uc = NULL;
1385 struct stream_out *curr_out = NULL;
1386
1387 list_for_each(node, &adev->usecase_list) {
1388 uc = node_to_item(node, struct audio_usecase, list);
1389 curr_out = (struct stream_out*) uc->stream.out;
1390
1391 if (curr_out && PCM_PLAYBACK == uc->type &&
1392 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1393 active = true;
1394 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301395 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301396 }
1397 }
1398 return active;
1399}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301400
1401static bool force_device_switch(struct audio_usecase *usecase)
1402{
1403 bool ret = false;
1404 bool is_it_true_mode = false;
1405
1406 if (is_offload_usecase(usecase->id) &&
1407 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001408 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1409 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1410 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301411 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1412 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1413 (!is_it_true_mode && adev->native_playback_enabled)){
1414 ret = true;
1415 ALOGD("napb: time to toggle native mode");
1416 }
1417 }
1418
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301419 // Force all a2dp output devices to reconfigure for proper AFE encode format
1420 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001421 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301422 audio_extn_a2dp_is_force_device_switch()) {
1423 ALOGD("Force a2dp device switch to update new encoder config");
1424 ret = true;
1425 }
1426
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301427 return ret;
1428}
1429
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001430int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001432 snd_device_t out_snd_device = SND_DEVICE_NONE;
1433 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 struct audio_usecase *usecase = NULL;
1435 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001436 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001437 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001438 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301441 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1442
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 usecase = get_usecase_from_list(adev, uc_id);
1444 if (usecase == NULL) {
1445 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1446 return -EINVAL;
1447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001449 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001450 (usecase->type == VOIP_CALL) ||
1451 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301452 if(usecase->stream.out == NULL) {
1453 ALOGE("%s: stream.out is NULL", __func__);
1454 return -EINVAL;
1455 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001456 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001457 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001458 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001459 usecase->devices = usecase->stream.out->devices;
1460 } else {
1461 /*
1462 * If the voice call is active, use the sound devices of voice call usecase
1463 * so that it would not result any device switch. All the usecases will
1464 * be switched to new device when select_devices() is called for voice call
1465 * usecase. This is to avoid switching devices for voice call when
1466 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001467 * choose voice call device only if the use case device is
1468 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001470 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001471 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001472 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001473 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1474 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301475 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1476 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001477 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 in_snd_device = vc_usecase->in_snd_device;
1479 out_snd_device = vc_usecase->out_snd_device;
1480 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001481 } else if (voice_extn_compress_voip_is_active(adev)) {
1482 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001483 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001484 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1485 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001486 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001487 in_snd_device = voip_usecase->in_snd_device;
1488 out_snd_device = voip_usecase->out_snd_device;
1489 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001490 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001491 hfp_ucid = audio_extn_hfp_get_usecase();
1492 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001493 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001494 in_snd_device = hfp_usecase->in_snd_device;
1495 out_snd_device = hfp_usecase->out_snd_device;
1496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 }
1498 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301499 if (usecase->stream.out == NULL) {
1500 ALOGE("%s: stream.out is NULL", __func__);
1501 return -EINVAL;
1502 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 usecase->devices = usecase->stream.out->devices;
1504 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001505 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001506 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001507 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001508 if (usecase->stream.out == adev->primary_output &&
1509 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001510 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001511 select_devices(adev, adev->active_input->usecase);
1512 }
1513 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001514 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301515 if (usecase->stream.in == NULL) {
1516 ALOGE("%s: stream.in is NULL", __func__);
1517 return -EINVAL;
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 usecase->devices = usecase->stream.in->device;
1520 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001521 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001522 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001523 if (adev->active_input &&
1524 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301525 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1526 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1527 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001528 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001529 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001530 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1531 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001533 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 }
1536 }
1537
1538 if (out_snd_device == usecase->out_snd_device &&
1539 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540
1541 if (!force_device_switch(usecase))
1542 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 }
1544
sangwoobc677242013-08-08 16:53:43 +09001545 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001546 out_snd_device, platform_get_snd_device_name(out_snd_device),
1547 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 /*
1550 * Limitation: While in call, to do a device switch we need to disable
1551 * and enable both RX and TX devices though one of them is same as current
1552 * device.
1553 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001554 if ((usecase->type == VOICE_CALL) &&
1555 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1556 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001558 }
1559
1560 if (((usecase->type == VOICE_CALL) ||
1561 (usecase->type == VOIP_CALL)) &&
1562 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1563 /* Disable sidetone only if voice/voip call already exists */
1564 if (voice_is_call_state_active(adev) ||
1565 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001566 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001567
1568 /* Disable aanc only if voice call exists */
1569 if (voice_is_call_state_active(adev))
1570 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001571 }
1572
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 /* Disable current sound devices */
1574 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001575 disable_audio_route(adev, usecase);
1576 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 }
1578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001580 disable_audio_route(adev, usecase);
1581 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001584 /* Applicable only on the targets that has external modem.
1585 * New device information should be sent to modem before enabling
1586 * the devices to reduce in-call device switch time.
1587 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001588 if ((usecase->type == VOICE_CALL) &&
1589 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1590 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001591 status = platform_switch_voice_call_enable_device_config(adev->platform,
1592 out_snd_device,
1593 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001594 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001595
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 /* Enable new sound devices */
1597 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001598 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301599 if (platform_check_codec_asrc_support(adev->platform))
1600 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001601 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 }
1603
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001604 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301605 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001606 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001607 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608
Avinash Vaish71a8b972014-07-24 15:36:33 +05301609 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001610 status = platform_switch_voice_call_device_post(adev->platform,
1611 out_snd_device,
1612 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301613 enable_audio_route_for_voice_usecases(adev, usecase);
1614 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001615
sangwoo170731f2013-06-08 15:36:36 +09001616 usecase->in_snd_device = in_snd_device;
1617 usecase->out_snd_device = out_snd_device;
1618
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301619 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1620 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301621 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001622 /* Notify device change info to effect clients registered */
1623 audio_extn_gef_notify_device_config(
1624 usecase->stream.out->devices,
1625 usecase->stream.out->channel_mask,
1626 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301627 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001629
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001630 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001631 /* Enable aanc only if voice call exists */
1632 if (voice_is_call_state_active(adev))
1633 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1634
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001635 /* Enable sidetone only if other voice/voip call already exists */
1636 if (voice_is_call_state_active(adev) ||
1637 voice_extn_compress_voip_is_started(adev))
1638 voice_set_sidetone(adev, out_snd_device, true);
1639 }
1640
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001641 /* Applicable only on the targets that has external modem.
1642 * Enable device command should be sent to modem only after
1643 * enabling voice call mixer controls
1644 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001645 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001646 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1647 out_snd_device,
1648 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301649 ALOGD("%s: done",__func__);
1650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 return status;
1652}
1653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654static int stop_input_stream(struct stream_in *in)
1655{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301656 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 struct audio_usecase *uc_info;
1658 struct audio_device *adev = in->dev;
1659
Dhananjay Kumard4833242016-10-06 22:09:12 +05301660 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Eric Laurent994a6932013-07-17 11:51:42 -07001662 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001663 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 uc_info = get_usecase_from_list(adev, in->usecase);
1665 if (uc_info == NULL) {
1666 ALOGE("%s: Could not find the usecase (%d) in the list",
1667 __func__, in->usecase);
1668 return -EINVAL;
1669 }
1670
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001671 /* Close in-call recording streams */
1672 voice_check_and_stop_incall_rec_usecase(adev, in);
1673
Eric Laurent150dbfe2013-02-27 14:31:02 -08001674 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001676
1677 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001678 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001680 list_remove(&uc_info->list);
1681 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682
Eric Laurent994a6932013-07-17 11:51:42 -07001683 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 return ret;
1685}
1686
1687int start_input_stream(struct stream_in *in)
1688{
1689 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001690 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 struct audio_usecase *uc_info;
1692 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301693 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694
Mingming Yin2664a5b2015-09-03 10:53:11 -07001695 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1696 if (get_usecase_from_list(adev, usecase) == NULL)
1697 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301698 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1699 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001700
Naresh Tanniru80659832014-06-04 18:17:56 +05301701
1702 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301703 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301704 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301705 goto error_config;
1706 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301707
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001708 /* Check if source matches incall recording usecase criteria */
1709 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1710 if (ret)
1711 goto error_config;
1712 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001713 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1714
1715 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1716 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1717 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001718 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001719 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001720
Eric Laurentb23d5282013-05-14 15:27:20 -07001721 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722 if (in->pcm_device_id < 0) {
1723 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1724 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001725 ret = -EINVAL;
1726 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728
1729 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001731
1732 if (!uc_info) {
1733 ret = -ENOMEM;
1734 goto error_config;
1735 }
1736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 uc_info->id = in->usecase;
1738 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001739 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740 uc_info->devices = in->device;
1741 uc_info->in_snd_device = SND_DEVICE_NONE;
1742 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001744 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301745 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1746 adev->perf_lock_opts,
1747 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301750 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1751 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001752
1753 unsigned int flags = PCM_IN;
1754 unsigned int pcm_open_retry_count = 0;
1755
1756 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1757 flags |= PCM_MMAP | PCM_NOIRQ;
1758 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001759 } else if (in->realtime) {
1760 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001761 }
1762
1763 while (1) {
1764 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1765 flags, &in->config);
1766 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1767 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1768 if (in->pcm != NULL) {
1769 pcm_close(in->pcm);
1770 in->pcm = NULL;
1771 }
1772 if (pcm_open_retry_count-- == 0) {
1773 ret = -EIO;
1774 goto error_open;
1775 }
1776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1777 continue;
1778 }
1779 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001781
1782 ALOGV("%s: pcm_prepare", __func__);
1783 ret = pcm_prepare(in->pcm);
1784 if (ret < 0) {
1785 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1786 pcm_close(in->pcm);
1787 in->pcm = NULL;
1788 goto error_open;
1789 }
1790
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001791 register_in_stream(in);
1792 if (in->realtime) {
1793 ret = pcm_start(in->pcm);
1794 if (ret < 0)
1795 goto error_open;
1796 }
1797
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301798 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001799 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001800
Eric Laurentc8400632013-02-14 19:04:54 -08001801 return ret;
1802
1803error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301804 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001806error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301807 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301808 /*
1809 * sleep 50ms to allow sufficient time for kernel
1810 * drivers to recover incases like SSR.
1811 */
1812 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001814
1815 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816}
1817
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001818void lock_input_stream(struct stream_in *in)
1819{
1820 pthread_mutex_lock(&in->pre_lock);
1821 pthread_mutex_lock(&in->lock);
1822 pthread_mutex_unlock(&in->pre_lock);
1823}
1824
1825void lock_output_stream(struct stream_out *out)
1826{
1827 pthread_mutex_lock(&out->pre_lock);
1828 pthread_mutex_lock(&out->lock);
1829 pthread_mutex_unlock(&out->pre_lock);
1830}
1831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832/* must be called with out->lock locked */
1833static int send_offload_cmd_l(struct stream_out* out, int command)
1834{
1835 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1836
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001837 if (!cmd) {
1838 ALOGE("failed to allocate mem for command 0x%x", command);
1839 return -ENOMEM;
1840 }
1841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842 ALOGVV("%s %d", __func__, command);
1843
1844 cmd->cmd = command;
1845 list_add_tail(&out->offload_cmd_list, &cmd->node);
1846 pthread_cond_signal(&out->offload_cond);
1847 return 0;
1848}
1849
1850/* must be called iwth out->lock locked */
1851static void stop_compressed_output_l(struct stream_out *out)
1852{
1853 out->offload_state = OFFLOAD_STATE_IDLE;
1854 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 if (out->compr != NULL) {
1857 compress_stop(out->compr);
1858 while (out->offload_thread_blocked) {
1859 pthread_cond_wait(&out->cond, &out->lock);
1860 }
1861 }
1862}
1863
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001864bool is_offload_usecase(audio_usecase_t uc_id)
1865{
1866 unsigned int i;
1867 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1868 if (uc_id == offload_usecases[i])
1869 return true;
1870 }
1871 return false;
1872}
1873
vivek mehta446c3962015-09-14 10:57:35 -07001874static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001875{
vivek mehta446c3962015-09-14 10:57:35 -07001876 audio_usecase_t ret_uc = USECASE_INVALID;
1877 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001878 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001879 if (!adev->multi_offload_enable) {
1880 if (is_direct_pcm)
1881 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1882 else
1883 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001884
vivek mehta446c3962015-09-14 10:57:35 -07001885 pthread_mutex_lock(&adev->lock);
1886 if (get_usecase_from_list(adev, ret_uc) != NULL)
1887 ret_uc = USECASE_INVALID;
1888 pthread_mutex_unlock(&adev->lock);
1889
1890 return ret_uc;
1891 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001892
1893 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001894 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1895 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1896 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1897 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001898 break;
1899 }
1900 }
vivek mehta446c3962015-09-14 10:57:35 -07001901
1902 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1903 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001904}
1905
1906static void free_offload_usecase(struct audio_device *adev,
1907 audio_usecase_t uc_id)
1908{
vivek mehta446c3962015-09-14 10:57:35 -07001909 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001910 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001911
1912 if (!adev->multi_offload_enable)
1913 return;
1914
1915 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1916 if (offload_usecases[offload_uc_index] == uc_id) {
1917 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918 break;
1919 }
1920 }
1921 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1922}
1923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924static void *offload_thread_loop(void *context)
1925{
1926 struct stream_out *out = (struct stream_out *) context;
1927 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001928 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1931 set_sched_policy(0, SP_FOREGROUND);
1932 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1933
1934 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001935 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 for (;;) {
1937 struct offload_cmd *cmd = NULL;
1938 stream_callback_event_t event;
1939 bool send_callback = false;
1940
1941 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1942 __func__, list_empty(&out->offload_cmd_list),
1943 out->offload_state);
1944 if (list_empty(&out->offload_cmd_list)) {
1945 ALOGV("%s SLEEPING", __func__);
1946 pthread_cond_wait(&out->offload_cond, &out->lock);
1947 ALOGV("%s RUNNING", __func__);
1948 continue;
1949 }
1950
1951 item = list_head(&out->offload_cmd_list);
1952 cmd = node_to_item(item, struct offload_cmd, node);
1953 list_remove(item);
1954
1955 ALOGVV("%s STATE %d CMD %d out->compr %p",
1956 __func__, out->offload_state, cmd->cmd, out->compr);
1957
1958 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1959 free(cmd);
1960 break;
1961 }
1962
1963 if (out->compr == NULL) {
1964 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001965 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 pthread_cond_signal(&out->cond);
1967 continue;
1968 }
1969 out->offload_thread_blocked = true;
1970 pthread_mutex_unlock(&out->lock);
1971 send_callback = false;
1972 switch(cmd->cmd) {
1973 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001974 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001975 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001976 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001977 send_callback = true;
1978 event = STREAM_CBK_EVENT_WRITE_READY;
1979 break;
1980 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001981 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301982 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001983 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301984 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001985 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301986 if (ret < 0)
1987 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301988 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301989 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001990 compress_drain(out->compr);
1991 else
1992 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301993 if (ret != -ENETRESET) {
1994 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301995 pthread_mutex_lock(&out->lock);
1996 out->send_new_metadata = 1;
1997 out->send_next_track_params = true;
1998 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301999 event = STREAM_CBK_EVENT_DRAIN_READY;
2000 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2001 } else
2002 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 break;
2004 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002005 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002007 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 send_callback = true;
2009 event = STREAM_CBK_EVENT_DRAIN_READY;
2010 break;
2011 default:
2012 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2013 break;
2014 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002015 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 out->offload_thread_blocked = false;
2017 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002018 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002019 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002021 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 free(cmd);
2023 }
2024
2025 pthread_cond_signal(&out->cond);
2026 while (!list_empty(&out->offload_cmd_list)) {
2027 item = list_head(&out->offload_cmd_list);
2028 list_remove(item);
2029 free(node_to_item(item, struct offload_cmd, node));
2030 }
2031 pthread_mutex_unlock(&out->lock);
2032
2033 return NULL;
2034}
2035
2036static int create_offload_callback_thread(struct stream_out *out)
2037{
2038 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2039 list_init(&out->offload_cmd_list);
2040 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2041 offload_thread_loop, out);
2042 return 0;
2043}
2044
2045static int destroy_offload_callback_thread(struct stream_out *out)
2046{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 stop_compressed_output_l(out);
2049 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2050
2051 pthread_mutex_unlock(&out->lock);
2052 pthread_join(out->offload_thread, (void **) NULL);
2053 pthread_cond_destroy(&out->offload_cond);
2054
2055 return 0;
2056}
2057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058static int stop_output_stream(struct stream_out *out)
2059{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 struct audio_usecase *uc_info;
2062 struct audio_device *adev = out->dev;
2063
Eric Laurent994a6932013-07-17 11:51:42 -07002064 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002065 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 uc_info = get_usecase_from_list(adev, out->usecase);
2067 if (uc_info == NULL) {
2068 ALOGE("%s: Could not find the usecase (%d) in the list",
2069 __func__, out->usecase);
2070 return -EINVAL;
2071 }
2072
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002073 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302074 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002075 if (adev->visualizer_stop_output != NULL)
2076 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002077
2078 audio_extn_dts_remove_state_notifier_node(out->usecase);
2079
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002080 if (adev->offload_effects_stop_output != NULL)
2081 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2082 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002083
Eric Laurent150dbfe2013-02-27 14:31:02 -08002084 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002085 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002086
2087 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002088 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002090 list_remove(&uc_info->list);
2091 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002093 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302094 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002095 ALOGV("Disable passthrough , reset mixer to pcm");
2096 /* NO_PASSTHROUGH */
2097 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002098 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002099 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2100 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002101
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302102 /* Must be called after removing the usecase from list */
2103 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302104 audio_extn_keep_alive_start();
2105
Eric Laurent994a6932013-07-17 11:51:42 -07002106 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 return ret;
2108}
2109
2110int start_output_stream(struct stream_out *out)
2111{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 struct audio_usecase *uc_info;
2114 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302115 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002117 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2118 ret = -EINVAL;
2119 goto error_config;
2120 }
2121
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302122 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2123 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2124 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302125
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302127 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302128 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302129 goto error_config;
2130 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302131
Eric Laurentb23d5282013-05-14 15:27:20 -07002132 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 if (out->pcm_device_id < 0) {
2134 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2135 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002136 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002137 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 }
2139
2140 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002141
2142 if (!uc_info) {
2143 ret = -ENOMEM;
2144 goto error_config;
2145 }
2146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 uc_info->id = out->usecase;
2148 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002149 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150 uc_info->devices = out->devices;
2151 uc_info->in_snd_device = SND_DEVICE_NONE;
2152 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002153 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302155 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2156 adev->perf_lock_opts,
2157 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302158
2159 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2160 audio_extn_keep_alive_stop();
2161 if (audio_extn_passthru_is_enabled() &&
2162 audio_extn_passthru_is_passthrough_stream(out)) {
2163 audio_extn_passthru_on_start(out);
2164 audio_extn_passthru_update_stream_configuration(adev, out);
2165 }
2166 }
2167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 select_devices(adev, out->usecase);
2169
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002170 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2171 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002172 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002173 unsigned int flags = PCM_OUT;
2174 unsigned int pcm_open_retry_count = 0;
2175 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2176 flags |= PCM_MMAP | PCM_NOIRQ;
2177 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002178 } else if (out->realtime) {
2179 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 } else
2181 flags |= PCM_MONOTONIC;
2182
2183 while (1) {
2184 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2185 flags, &out->config);
2186 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2187 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2188 if (out->pcm != NULL) {
2189 pcm_close(out->pcm);
2190 out->pcm = NULL;
2191 }
2192 if (pcm_open_retry_count-- == 0) {
2193 ret = -EIO;
2194 goto error_open;
2195 }
2196 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2197 continue;
2198 }
2199 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002201
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002202 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2203 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002204
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002205 ALOGV("%s: pcm_prepare", __func__);
2206 if (pcm_is_ready(out->pcm)) {
2207 ret = pcm_prepare(out->pcm);
2208 if (ret < 0) {
2209 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2210 pcm_close(out->pcm);
2211 out->pcm = NULL;
2212 goto error_open;
2213 }
2214 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002216 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2217 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002219 out->compr = compress_open(adev->snd_card,
2220 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 COMPRESS_IN, &out->compr_config);
2222 if (out->compr && !is_compress_ready(out->compr)) {
2223 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2224 compress_close(out->compr);
2225 out->compr = NULL;
2226 ret = -EIO;
2227 goto error_open;
2228 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302229 /* compress_open sends params of the track, so reset the flag here */
2230 out->is_compr_metadata_avail = false;
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 if (out->offload_callback)
2233 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002234
Fred Oh3f43e742015-03-04 18:42:34 -08002235 /* Since small bufs uses blocking writes, a write will be blocked
2236 for the default max poll time (20s) in the event of an SSR.
2237 Reduce the poll time to observe and deal with SSR faster.
2238 */
Ashish Jain5106d362016-05-11 19:23:33 +05302239 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002240 compress_set_max_poll_wait(out->compr, 1000);
2241 }
2242
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002243 audio_extn_dts_create_state_notifier_node(out->usecase);
2244 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2245 popcount(out->channel_mask),
2246 out->playback_started);
2247
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002248#ifdef DS1_DOLBY_DDP_ENABLED
2249 if (audio_extn_is_dolby_format(out->format))
2250 audio_extn_dolby_send_ddp_endp_params(adev);
2251#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302252 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002253 if (adev->visualizer_start_output != NULL)
2254 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2255 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302256 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002257 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002260
2261 if (ret == 0) {
2262 register_out_stream(out);
2263 if (out->realtime) {
2264 ret = pcm_start(out->pcm);
2265 if (ret < 0)
2266 goto error_open;
2267 }
2268 }
2269
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302270 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002271 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002272
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002273 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302275 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002277error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302278 /*
2279 * sleep 50ms to allow sufficient time for kernel
2280 * drivers to recover incases like SSR.
2281 */
2282 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284}
2285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286static int check_input_parameters(uint32_t sample_rate,
2287 audio_format_t format,
2288 int channel_count)
2289{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002290 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302292 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2293 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2294 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002295 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302296 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002297
2298 switch (channel_count) {
2299 case 1:
2300 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302301 case 3:
2302 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002303 case 6:
2304 break;
2305 default:
2306 ret = -EINVAL;
2307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308
2309 switch (sample_rate) {
2310 case 8000:
2311 case 11025:
2312 case 12000:
2313 case 16000:
2314 case 22050:
2315 case 24000:
2316 case 32000:
2317 case 44100:
2318 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302319 case 96000:
2320 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 break;
2322 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002323 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 }
2325
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002326 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327}
2328
2329static size_t get_input_buffer_size(uint32_t sample_rate,
2330 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002331 int channel_count,
2332 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 size_t size = 0;
2335
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002336 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2337 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002339 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002340 if (is_low_latency)
2341 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302342
2343 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002345 /* make sure the size is multiple of 32 bytes
2346 * At 48 kHz mono 16-bit PCM:
2347 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2348 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2349 */
2350 size += 0x1f;
2351 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002352
2353 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354}
2355
Ashish Jain058165c2016-09-28 23:18:48 +05302356static size_t get_output_period_size(uint32_t sample_rate,
2357 audio_format_t format,
2358 int channel_count,
2359 int duration /*in millisecs*/)
2360{
2361 size_t size = 0;
2362 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2363
2364 if ((duration == 0) || (sample_rate == 0) ||
2365 (bytes_per_sample == 0) || (channel_count == 0)) {
2366 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2367 bytes_per_sample, channel_count);
2368 return -EINVAL;
2369 }
2370
2371 size = (sample_rate *
2372 duration *
2373 bytes_per_sample *
2374 channel_count) / 1000;
2375 /*
2376 * To have same PCM samples for all channels, the buffer size requires to
2377 * be multiple of (number of channels * bytes per sample)
2378 * For writes to succeed, the buffer must be written at address which is multiple of 32
2379 */
2380 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2381
2382 return (size/(channel_count * bytes_per_sample));
2383}
2384
Ashish Jain5106d362016-05-11 19:23:33 +05302385static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2386{
2387 uint64_t actual_frames_rendered = 0;
2388 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2389
2390 /* This adjustment accounts for buffering after app processor.
2391 * It is based on estimated DSP latency per use case, rather than exact.
2392 */
2393 int64_t platform_latency = platform_render_latency(out->usecase) *
2394 out->sample_rate / 1000000LL;
2395
2396 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2397 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2398 * hence only estimate.
2399 */
2400 int64_t signed_frames = out->written - kernel_buffer_size;
2401
2402 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2403
2404 if (signed_frames > 0)
2405 actual_frames_rendered = signed_frames;
2406
2407 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2408 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2409 (long long int)out->written, (int)kernel_buffer_size,
2410 audio_bytes_per_sample(out->compr_config.codec->format),
2411 popcount(out->channel_mask));
2412
2413 return actual_frames_rendered;
2414}
2415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2417{
2418 struct stream_out *out = (struct stream_out *)stream;
2419
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421}
2422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002423static int out_set_sample_rate(struct audio_stream *stream __unused,
2424 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
2426 return -ENOSYS;
2427}
2428
2429static size_t out_get_buffer_size(const struct audio_stream *stream)
2430{
2431 struct stream_out *out = (struct stream_out *)stream;
2432
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002433 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002435 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2436 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302437 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302438 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002440 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002441 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442}
2443
2444static uint32_t out_get_channels(const struct audio_stream *stream)
2445{
2446 struct stream_out *out = (struct stream_out *)stream;
2447
2448 return out->channel_mask;
2449}
2450
2451static audio_format_t out_get_format(const struct audio_stream *stream)
2452{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 struct stream_out *out = (struct stream_out *)stream;
2454
2455 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002458static int out_set_format(struct audio_stream *stream __unused,
2459 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460{
2461 return -ENOSYS;
2462}
2463
2464static int out_standby(struct audio_stream *stream)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302469 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2470 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002472 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002474 if (adev->adm_deregister_stream)
2475 adev->adm_deregister_stream(adev->adm_data, out->handle);
2476
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002477 if (is_offload_usecase(out->usecase))
2478 stop_compressed_output_l(out);
2479
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002480 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002482 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2483 voice_extn_compress_voip_close_output_stream(stream);
2484 pthread_mutex_unlock(&adev->lock);
2485 pthread_mutex_unlock(&out->lock);
2486 ALOGD("VOIP output entered standby");
2487 return 0;
2488 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 if (out->pcm) {
2490 pcm_close(out->pcm);
2491 out->pcm = NULL;
2492 }
2493 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002494 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302495 out->send_next_track_params = false;
2496 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002497 out->gapless_mdata.encoder_delay = 0;
2498 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 if (out->compr != NULL) {
2500 compress_close(out->compr);
2501 out->compr = NULL;
2502 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002505 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
2507 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302508 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 return 0;
2510}
2511
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002512static int out_dump(const struct audio_stream *stream __unused,
2513 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514{
2515 return 0;
2516}
2517
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2519{
2520 int ret = 0;
2521 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002522
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002523 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002524 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002525 return -EINVAL;
2526 }
2527
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302528 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002529
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002530 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2531 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302532 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002533 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2535 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302536 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002537 }
2538
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002539 ALOGV("%s new encoder delay %u and padding %u", __func__,
2540 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2541
2542 return 0;
2543}
2544
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002545static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2546{
2547 return out == adev->primary_output || out == adev->voice_tx_output;
2548}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2551{
2552 struct stream_out *out = (struct stream_out *)stream;
2553 struct audio_device *adev = out->dev;
2554 struct str_parms *parms;
2555 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002556 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
sangwoobc677242013-08-08 16:53:43 +09002558 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002559 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302561 if (!parms)
2562 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002563 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2564 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002566 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002567 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002570 * When HDMI cable is unplugged the music playback is paused and
2571 * the policy manager sends routing=0. But the audioflinger continues
2572 * to write data until standby time (3sec). As the HDMI core is
2573 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 * Avoid this by routing audio to speaker until standby.
2575 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002576 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2577 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302578 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002579 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2580 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002581 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302582 /*
2583 * When A2DP is disconnected the
2584 * music playback is paused and the policy manager sends routing=0
2585 * But the audioflingercontinues to write data until standby time
2586 * (3sec). As BT is turned off, the write gets blocked.
2587 * Avoid this by routing audio to speaker until standby.
2588 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002589 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302590 (val == AUDIO_DEVICE_NONE)) {
2591 val = AUDIO_DEVICE_OUT_SPEAKER;
2592 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302593 /* To avoid a2dp to sco overlapping force route BT usecases
2594 * to speaker based on Phone state
2595 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002596 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302597 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2598 (adev->mode == AUDIO_MODE_IN_CALL))) {
2599 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2600 val = AUDIO_DEVICE_OUT_SPEAKER;
2601 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002602 /*
2603 * select_devices() call below switches all the usecases on the same
2604 * backend to the new device. Refer to check_usecases_codec_backend() in
2605 * the select_devices(). But how do we undo this?
2606 *
2607 * For example, music playback is active on headset (deep-buffer usecase)
2608 * and if we go to ringtones and select a ringtone, low-latency usecase
2609 * will be started on headset+speaker. As we can't enable headset+speaker
2610 * and headset devices at the same time, select_devices() switches the music
2611 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2612 * So when the ringtone playback is completed, how do we undo the same?
2613 *
2614 * We are relying on the out_set_parameters() call on deep-buffer output,
2615 * once the ringtone playback is ended.
2616 * NOTE: We should not check if the current devices are same as new devices.
2617 * Because select_devices() must be called to switch back the music
2618 * playback to headset.
2619 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002620 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002621 audio_devices_t new_dev = val;
2622 bool same_dev = out->devices == new_dev;
2623 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002624
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002625 if (output_drives_call(adev, out)) {
2626 if(!voice_is_in_call(adev)) {
2627 if (adev->mode == AUDIO_MODE_IN_CALL) {
2628 adev->current_call_output = out;
2629 ret = voice_start_call(adev);
2630 }
2631 } else {
2632 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002633 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002634 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002635 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002636
2637 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002638 if (!same_dev) {
2639 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302640 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2641 adev->perf_lock_opts,
2642 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002643 if (adev->adm_on_routing_change)
2644 adev->adm_on_routing_change(adev->adm_data,
2645 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002646 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002647 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302648 if (!same_dev)
2649 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002650 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002651 }
2652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002654 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002656
2657 if (out == adev->primary_output) {
2658 pthread_mutex_lock(&adev->lock);
2659 audio_extn_set_parameters(adev, parms);
2660 pthread_mutex_unlock(&adev->lock);
2661 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002662 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002663 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002664 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002665
2666 audio_extn_dts_create_state_notifier_node(out->usecase);
2667 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2668 popcount(out->channel_mask),
2669 out->playback_started);
2670
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002671 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002672 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302675error:
Eric Laurent994a6932013-07-17 11:51:42 -07002676 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 return ret;
2678}
2679
2680static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2681{
2682 struct stream_out *out = (struct stream_out *)stream;
2683 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002684 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 char value[256];
2686 struct str_parms *reply = str_parms_create();
2687 size_t i, j;
2688 int ret;
2689 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002690
2691 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002692 if (reply) {
2693 str_parms_destroy(reply);
2694 }
2695 if (query) {
2696 str_parms_destroy(query);
2697 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002698 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2699 return NULL;
2700 }
2701
Eric Laurent994a6932013-07-17 11:51:42 -07002702 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2704 if (ret >= 0) {
2705 value[0] = '\0';
2706 i = 0;
2707 while (out->supported_channel_masks[i] != 0) {
2708 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2709 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2710 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002711 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002713 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 first = false;
2715 break;
2716 }
2717 }
2718 i++;
2719 }
2720 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2721 str = str_parms_to_str(reply);
2722 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002723 voice_extn_out_get_parameters(out, query, reply);
2724 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002725 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002726 free(str);
2727 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002730
Alexy Joseph62142aa2015-11-16 15:10:34 -08002731
2732 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2733 if (ret >= 0) {
2734 value[0] = '\0';
2735 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2736 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302737 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002738 } else {
2739 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302740 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002741 }
2742 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002743 if (str)
2744 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002745 str = str_parms_to_str(reply);
2746 }
2747
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002748 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2749 if (ret >= 0) {
2750 value[0] = '\0';
2751 i = 0;
2752 first = true;
2753 while (out->supported_formats[i] != 0) {
2754 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2755 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2756 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002757 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002758 }
2759 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2760 first = false;
2761 break;
2762 }
2763 }
2764 i++;
2765 }
2766 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002767 if (str)
2768 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002769 str = str_parms_to_str(reply);
2770 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002771
2772 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2773 if (ret >= 0) {
2774 value[0] = '\0';
2775 i = 0;
2776 first = true;
2777 while (out->supported_sample_rates[i] != 0) {
2778 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2779 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2780 if (!first) {
2781 strlcat(value, "|", sizeof(value));
2782 }
2783 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2784 first = false;
2785 break;
2786 }
2787 }
2788 i++;
2789 }
2790 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2791 if (str)
2792 free(str);
2793 str = str_parms_to_str(reply);
2794 }
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 str_parms_destroy(query);
2797 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002798 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 return str;
2800}
2801
2802static uint32_t out_get_latency(const struct audio_stream_out *stream)
2803{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002804 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002806 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807
Alexy Josephaa54c872014-12-03 02:46:47 -08002808 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002809 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002810 } else if (out->realtime) {
2811 // since the buffer won't be filled up faster than realtime,
2812 // return a smaller number
2813 if (out->config.rate)
2814 period_ms = (out->af_period_multiplier * out->config.period_size *
2815 1000) / (out->config.rate);
2816 else
2817 period_ms = 0;
2818 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002819 } else {
2820 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002822 }
2823
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302824 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002825 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826}
2827
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302828static float AmpToDb(float amplification)
2829{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302830 float db = DSD_VOLUME_MIN_DB;
2831 if (amplification > 0) {
2832 db = 20 * log10(amplification);
2833 if(db < DSD_VOLUME_MIN_DB)
2834 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302835 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302836 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302837}
2838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839static int out_set_volume(struct audio_stream_out *stream, float left,
2840 float right)
2841{
Eric Laurenta9024de2013-04-04 09:19:12 -07002842 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 int volume[2];
2844
Eric Laurenta9024de2013-04-04 09:19:12 -07002845 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2846 /* only take left channel into account: the API is for stereo anyway */
2847 out->muted = (left == 0.0f);
2848 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002849 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302850 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002851 /*
2852 * Set mute or umute on HDMI passthrough stream.
2853 * Only take left channel into account.
2854 * Mute is 0 and unmute 1
2855 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302856 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302857 } else if (out->format == AUDIO_FORMAT_DSD){
2858 char mixer_ctl_name[128] = "DSD Volume";
2859 struct audio_device *adev = out->dev;
2860 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2861
2862 if (!ctl) {
2863 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2864 __func__, mixer_ctl_name);
2865 return -EINVAL;
2866 }
2867 volume[0] = (int)(AmpToDb(left));
2868 volume[1] = (int)(AmpToDb(right));
2869 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2870 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002871 } else {
2872 char mixer_ctl_name[128];
2873 struct audio_device *adev = out->dev;
2874 struct mixer_ctl *ctl;
2875 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002876 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002878 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2879 "Compress Playback %d Volume", pcm_device_id);
2880 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2881 if (!ctl) {
2882 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2883 __func__, mixer_ctl_name);
2884 return -EINVAL;
2885 }
2886 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2887 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2888 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2889 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002891 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 return -ENOSYS;
2894}
2895
2896static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2897 size_t bytes)
2898{
2899 struct stream_out *out = (struct stream_out *)stream;
2900 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302901 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002902 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002904 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302905
Naresh Tanniru80659832014-06-04 18:17:56 +05302906 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002907
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302908 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302909 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302910 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2911 pthread_mutex_unlock(&out->lock);
2912 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302913 } else {
2914 /* increase written size during SSR to avoid mismatch
2915 * with the written frames count in AF
2916 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002917 // bytes per frame
2918 size_t bpf = audio_bytes_per_sample(out->format) *
2919 audio_channel_count_from_out_mask(out->channel_mask);
2920 if (bpf != 0)
2921 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302922 ALOGD(" %s: sound card is not active/SSR state", __func__);
2923 ret= -EIO;
2924 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302925 }
2926 }
2927
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302928 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302929 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2930 if (audio_bytes_per_sample(out->format) != 0)
2931 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2932 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302933 goto exit;
2934 }
2935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002937 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002938 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002939 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2940 ret = voice_extn_compress_voip_start_output_stream(out);
2941 else
2942 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002943 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002946 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947 goto exit;
2948 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002949
2950 if (last_known_cal_step != -1) {
2951 ALOGD("%s: retry previous failed cal level set", __func__);
2952 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2953 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955
Ashish Jain81eb2a82015-05-13 10:52:34 +05302956 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002957 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302958 adev->is_channel_status_set = true;
2959 }
2960
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002961 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002962 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002963 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002964 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002965 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2966 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302967 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2968 ALOGD("copl(%p):send next track params in gapless", out);
2969 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2970 out->send_next_track_params = false;
2971 out->is_compr_metadata_avail = false;
2972 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002973 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302974 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302975 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002976
Ashish Jain83a6cc22016-06-28 14:34:17 +05302977 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302978 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302979 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302980 pthread_mutex_unlock(&out->lock);
2981 return -EINVAL;
2982 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302983 audio_format_t dst_format = out->hal_op_format;
2984 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302985
2986 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2987 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2988
Ashish Jain83a6cc22016-06-28 14:34:17 +05302989 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302990 dst_format,
2991 buffer,
2992 src_format,
2993 frames);
2994
Ashish Jain83a6cc22016-06-28 14:34:17 +05302995 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302996 bytes_to_write);
2997
2998 /*Convert written bytes in audio flinger format*/
2999 if (ret > 0)
3000 ret = ((ret * format_to_bitwidth_table[out->format]) /
3001 format_to_bitwidth_table[dst_format]);
3002 }
3003 } else
3004 ret = compress_write(out->compr, buffer, bytes);
3005
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303006 if (ret < 0)
3007 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303008 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303009 /*msg to cb thread only if non blocking write is enabled*/
3010 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303011 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303013 } else if (-ENETRESET == ret) {
3014 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3015 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3016 pthread_mutex_unlock(&out->lock);
3017 out_standby(&out->stream.common);
3018 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003019 }
Ashish Jain5106d362016-05-11 19:23:33 +05303020 if ( ret == (ssize_t)bytes && !out->non_blocking)
3021 out->written += bytes;
3022
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303023 /* Call compr start only when non-zero bytes of data is there to be rendered */
3024 if (!out->playback_started && ret > 0) {
3025 int status = compress_start(out->compr);
3026 if (status < 0) {
3027 ret = status;
3028 ALOGE("%s: compr start failed with err %d", __func__, errno);
3029 goto exit;
3030 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003031 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 out->playback_started = 1;
3033 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003034
3035 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3036 popcount(out->channel_mask),
3037 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038 }
3039 pthread_mutex_unlock(&out->lock);
3040 return ret;
3041 } else {
3042 if (out->pcm) {
3043 if (out->muted)
3044 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003045
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303046 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003047
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003048 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003049
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003050 if (out->config.rate)
3051 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3052 out->config.rate;
3053
3054 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3055
3056 request_out_focus(out, ns);
3057
3058 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003059 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003060 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303061 out->convert_buffer != NULL) {
3062
3063 memcpy_by_audio_format(out->convert_buffer,
3064 out->hal_op_format,
3065 buffer,
3066 out->hal_ip_format,
3067 out->config.period_size * out->config.channels);
3068
3069 ret = pcm_write(out->pcm, out->convert_buffer,
3070 (out->config.period_size *
3071 out->config.channels *
3072 format_to_bitwidth_table[out->hal_op_format]));
3073 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003074 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303075 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003076
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003077 release_out_focus(out);
3078
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303079 if (ret < 0)
3080 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303081 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3082 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3083 else
3084 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 }
3087
3088exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303089 /* ToDo: There may be a corner case when SSR happens back to back during
3090 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303091 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303092 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303093 }
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 pthread_mutex_unlock(&out->lock);
3096
3097 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003098 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003099 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303100 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303101 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303102 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303103 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303104 out->standby = true;
3105 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303107 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3108 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3109 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 }
3111 return bytes;
3112}
3113
3114static int out_get_render_position(const struct audio_stream_out *stream,
3115 uint32_t *dsp_frames)
3116{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303118 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003119
3120 if (dsp_frames == NULL)
3121 return -EINVAL;
3122
3123 *dsp_frames = 0;
3124 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003125 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303126
3127 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3128 * this operation and adev_close_output_stream(where out gets reset).
3129 */
3130 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3131 *dsp_frames = get_actual_pcm_frames_rendered(out);
3132 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3133 return 0;
3134 }
3135
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003136 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303137 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303138 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303140 if (ret < 0)
3141 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303143 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 }
3145 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303146 if (-ENETRESET == ret) {
3147 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3148 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3149 return -EINVAL;
3150 } else if(ret < 0) {
3151 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3152 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303153 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3154 /*
3155 * Handle corner case where compress session is closed during SSR
3156 * and timestamp is queried
3157 */
3158 ALOGE(" ERROR: sound card not active, return error");
3159 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303160 } else {
3161 return 0;
3162 }
Zhou Song32a556e2015-05-05 10:46:56 +08003163 } else if (audio_is_linear_pcm(out->format)) {
3164 *dsp_frames = out->written;
3165 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166 } else
3167 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168}
3169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003170static int out_add_audio_effect(const struct audio_stream *stream __unused,
3171 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172{
3173 return 0;
3174}
3175
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003176static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3177 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178{
3179 return 0;
3180}
3181
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003182static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3183 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184{
3185 return -EINVAL;
3186}
3187
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003188static int out_get_presentation_position(const struct audio_stream_out *stream,
3189 uint64_t *frames, struct timespec *timestamp)
3190{
3191 struct stream_out *out = (struct stream_out *)stream;
3192 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003193 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003194
Ashish Jain5106d362016-05-11 19:23:33 +05303195 /* below piece of code is not guarded against any lock because audioFliner serializes
3196 * this operation and adev_close_output_stream( where out gets reset).
3197 */
3198 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3199 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3200 *frames = get_actual_pcm_frames_rendered(out);
3201 /* this is the best we can do */
3202 clock_gettime(CLOCK_MONOTONIC, timestamp);
3203 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3204 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3205 return 0;
3206 }
3207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003208 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003209
Ashish Jain5106d362016-05-11 19:23:33 +05303210 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3211 ret = compress_get_tstamp(out->compr, &dsp_frames,
3212 &out->sample_rate);
3213 ALOGVV("%s rendered frames %ld sample_rate %d",
3214 __func__, dsp_frames, out->sample_rate);
3215 *frames = dsp_frames;
3216 if (ret < 0)
3217 ret = -errno;
3218 if (-ENETRESET == ret) {
3219 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3221 ret = -EINVAL;
3222 } else
3223 ret = 0;
3224 /* this is the best we can do */
3225 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003226 } else {
3227 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003228 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003229 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3230 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003231 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003232 // This adjustment accounts for buffering after app processor.
3233 // It is based on estimated DSP latency per use case, rather than exact.
3234 signed_frames -=
3235 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3236
Eric Laurent949a0892013-09-20 09:20:13 -07003237 // It would be unusual for this value to be negative, but check just in case ...
3238 if (signed_frames >= 0) {
3239 *frames = signed_frames;
3240 ret = 0;
3241 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003242 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303243 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3244 *frames = out->written;
3245 clock_gettime(CLOCK_MONOTONIC, timestamp);
3246 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003247 }
3248 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003249 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003250 return ret;
3251}
3252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253static int out_set_callback(struct audio_stream_out *stream,
3254 stream_callback_t callback, void *cookie)
3255{
3256 struct stream_out *out = (struct stream_out *)stream;
3257
3258 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003259 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 out->offload_callback = callback;
3261 out->offload_cookie = cookie;
3262 pthread_mutex_unlock(&out->lock);
3263 return 0;
3264}
3265
3266static int out_pause(struct audio_stream_out* stream)
3267{
3268 struct stream_out *out = (struct stream_out *)stream;
3269 int status = -ENOSYS;
3270 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003271 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003272 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003273 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303275 struct audio_device *adev = out->dev;
3276 int snd_scard_state = get_snd_card_state(adev);
3277
3278 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3279 status = compress_pause(out->compr);
3280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003281 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003282
Mingming Yin21854652016-04-13 11:54:02 -07003283 if (audio_extn_passthru_is_active()) {
3284 ALOGV("offload use case, pause passthru");
3285 audio_extn_passthru_on_pause(out);
3286 }
3287
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303288 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003289 audio_extn_dts_notify_playback_state(out->usecase, 0,
3290 out->sample_rate, popcount(out->channel_mask),
3291 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 }
3293 pthread_mutex_unlock(&out->lock);
3294 }
3295 return status;
3296}
3297
3298static int out_resume(struct audio_stream_out* stream)
3299{
3300 struct stream_out *out = (struct stream_out *)stream;
3301 int status = -ENOSYS;
3302 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003303 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003304 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003306 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303308 struct audio_device *adev = out->dev;
3309 int snd_scard_state = get_snd_card_state(adev);
3310
Mingming Yin21854652016-04-13 11:54:02 -07003311 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3312 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3313 pthread_mutex_lock(&out->dev->lock);
3314 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003315 pthread_mutex_unlock(&out->dev->lock);
3316 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303317 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003318 }
3319 if (!status) {
3320 out->offload_state = OFFLOAD_STATE_PLAYING;
3321 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303322 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003323 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3324 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003325 }
3326 pthread_mutex_unlock(&out->lock);
3327 }
3328 return status;
3329}
3330
3331static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3332{
3333 struct stream_out *out = (struct stream_out *)stream;
3334 int status = -ENOSYS;
3335 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003336 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003337 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3339 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3340 else
3341 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3342 pthread_mutex_unlock(&out->lock);
3343 }
3344 return status;
3345}
3346
3347static int out_flush(struct audio_stream_out* stream)
3348{
3349 struct stream_out *out = (struct stream_out *)stream;
3350 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003352 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003353 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003354 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3355 stop_compressed_output_l(out);
3356 out->written = 0;
3357 } else {
3358 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3359 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003361 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 return 0;
3363 }
3364 return -ENOSYS;
3365}
3366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367/** audio_stream_in implementation **/
3368static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3369{
3370 struct stream_in *in = (struct stream_in *)stream;
3371
3372 return in->config.rate;
3373}
3374
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003375static int in_set_sample_rate(struct audio_stream *stream __unused,
3376 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377{
3378 return -ENOSYS;
3379}
3380
3381static size_t in_get_buffer_size(const struct audio_stream *stream)
3382{
3383 struct stream_in *in = (struct stream_in *)stream;
3384
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003385 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3386 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003387 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3388 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003389
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003390 return in->config.period_size * in->af_period_multiplier *
3391 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392}
3393
3394static uint32_t in_get_channels(const struct audio_stream *stream)
3395{
3396 struct stream_in *in = (struct stream_in *)stream;
3397
3398 return in->channel_mask;
3399}
3400
3401static audio_format_t in_get_format(const struct audio_stream *stream)
3402{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003403 struct stream_in *in = (struct stream_in *)stream;
3404
3405 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406}
3407
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003408static int in_set_format(struct audio_stream *stream __unused,
3409 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410{
3411 return -ENOSYS;
3412}
3413
3414static int in_standby(struct audio_stream *stream)
3415{
3416 struct stream_in *in = (struct stream_in *)stream;
3417 struct audio_device *adev = in->dev;
3418 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303419 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3420 stream, in->usecase, use_case_table[in->usecase]);
3421
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003422 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003423 if (!in->standby && in->is_st_session) {
3424 ALOGD("%s: sound trigger pcm stop lab", __func__);
3425 audio_extn_sound_trigger_stop_lab(in);
3426 in->standby = 1;
3427 }
3428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003430 if (adev->adm_deregister_stream)
3431 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3432
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003433 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003435 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3436 voice_extn_compress_voip_close_input_stream(stream);
3437 ALOGD("VOIP input entered standby");
3438 } else {
3439 if (in->pcm) {
3440 pcm_close(in->pcm);
3441 in->pcm = NULL;
3442 }
3443 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003444 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003445 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 }
3447 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003448 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 return status;
3450}
3451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003452static int in_dump(const struct audio_stream *stream __unused,
3453 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454{
3455 return 0;
3456}
3457
3458static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3459{
3460 struct stream_in *in = (struct stream_in *)stream;
3461 struct audio_device *adev = in->dev;
3462 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003464 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303466 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 parms = str_parms_create_str(kvpairs);
3468
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303469 if (!parms)
3470 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003471 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003472 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003473
3474 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3475 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 val = atoi(value);
3477 /* no audio source uses val == 0 */
3478 if ((in->source != val) && (val != 0)) {
3479 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003480 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3481 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3482 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003483 (in->config.rate == 8000 || in->config.rate == 16000 ||
3484 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003485 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003486 err = voice_extn_compress_voip_open_input_stream(in);
3487 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003488 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003489 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003490 }
3491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 }
3493 }
3494
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003495 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3496 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003498 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 in->device = val;
3500 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003501 if (!in->standby && !in->is_st_session) {
3502 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003503 if (adev->adm_on_routing_change)
3504 adev->adm_on_routing_change(adev->adm_data,
3505 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003506 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 }
3509 }
3510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003512 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513
3514 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303515error:
Eric Laurent994a6932013-07-17 11:51:42 -07003516 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 return ret;
3518}
3519
3520static char* in_get_parameters(const struct audio_stream *stream,
3521 const char *keys)
3522{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003523 struct stream_in *in = (struct stream_in *)stream;
3524 struct str_parms *query = str_parms_create_str(keys);
3525 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003526 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003527
3528 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003529 if (reply) {
3530 str_parms_destroy(reply);
3531 }
3532 if (query) {
3533 str_parms_destroy(query);
3534 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003535 ALOGE("in_get_parameters: failed to create query or reply");
3536 return NULL;
3537 }
3538
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003539 ALOGV("%s: enter: keys - %s", __func__, keys);
3540
3541 voice_extn_in_get_parameters(in, query, reply);
3542
3543 str = str_parms_to_str(reply);
3544 str_parms_destroy(query);
3545 str_parms_destroy(reply);
3546
3547 ALOGV("%s: exit: returns - %s", __func__, str);
3548 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549}
3550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003551static int in_set_gain(struct audio_stream_in *stream __unused,
3552 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
3554 return 0;
3555}
3556
3557static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3558 size_t bytes)
3559{
3560 struct stream_in *in = (struct stream_in *)stream;
3561 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303562 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303563 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303564 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003566 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303567
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003568 if (in->is_st_session) {
3569 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3570 /* Read from sound trigger HAL */
3571 audio_extn_sound_trigger_read(in, buffer, bytes);
3572 pthread_mutex_unlock(&in->lock);
3573 return bytes;
3574 }
3575
Ashish Jainbbce4322016-02-16 13:25:27 +05303576 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003577 ALOGD(" %s: sound card is not active/SSR state", __func__);
3578 ret= -EIO;;
3579 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303580 }
3581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003583 pthread_mutex_lock(&adev->lock);
3584 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3585 ret = voice_extn_compress_voip_start_input_stream(in);
3586 else
3587 ret = start_input_stream(in);
3588 pthread_mutex_unlock(&adev->lock);
3589 if (ret != 0) {
3590 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 }
3592 in->standby = 0;
3593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003595 // what's the duration requested by the client?
3596 long ns = 0;
3597
3598 if (in->config.rate)
3599 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3600 in->config.rate;
3601
3602 request_in_focus(in, ns);
3603 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303606 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003607 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303608 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003609 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003610 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003611 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303612 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003613 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303614 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3615 if (bytes % 4 == 0) {
3616 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3617 int_buf_stream = buffer;
Yamit Mehtaa0d653a2016-11-25 20:33:25 +05303618 size_t itt = 0;
3619 for (itt = 0; itt < bytes/4 ; itt++) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303620 int_buf_stream[itt] >>= 8;
3621 }
3622 } else {
3623 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3624 ret = -EINVAL;
3625 goto exit;
3626 }
3627 } if (ret < 0) {
3628 ret = -errno;
3629 }
3630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 }
3632
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003633 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 /*
3636 * Instead of writing zeroes here, we could trust the hardware
3637 * to always provide zeroes when muted.
3638 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303639 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3640 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 memset(buffer, 0, bytes);
3642
3643exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303644 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303645 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003646 if (-ENETRESET == ret)
3647 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 pthread_mutex_unlock(&in->lock);
3650
3651 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303652 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303653 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303654 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303655 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303656 in->standby = true;
3657 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303658 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003660 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303661 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303662 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 }
3664 return bytes;
3665}
3666
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003667static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668{
3669 return 0;
3670}
3671
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003672static int add_remove_audio_effect(const struct audio_stream *stream,
3673 effect_handle_t effect,
3674 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003676 struct stream_in *in = (struct stream_in *)stream;
3677 int status = 0;
3678 effect_descriptor_t desc;
3679
3680 status = (*effect)->get_descriptor(effect, &desc);
3681 if (status != 0)
3682 return status;
3683
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003684 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003685 pthread_mutex_lock(&in->dev->lock);
3686 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3687 in->enable_aec != enable &&
3688 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3689 in->enable_aec = enable;
3690 if (!in->standby)
3691 select_devices(in->dev, in->usecase);
3692 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003693 if (in->enable_ns != enable &&
3694 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3695 in->enable_ns = enable;
3696 if (!in->standby)
3697 select_devices(in->dev, in->usecase);
3698 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003699 pthread_mutex_unlock(&in->dev->lock);
3700 pthread_mutex_unlock(&in->lock);
3701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 return 0;
3703}
3704
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003705static int in_add_audio_effect(const struct audio_stream *stream,
3706 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707{
Eric Laurent994a6932013-07-17 11:51:42 -07003708 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003709 return add_remove_audio_effect(stream, effect, true);
3710}
3711
3712static int in_remove_audio_effect(const struct audio_stream *stream,
3713 effect_handle_t effect)
3714{
Eric Laurent994a6932013-07-17 11:51:42 -07003715 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003716 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717}
3718
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303719int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 audio_io_handle_t handle,
3721 audio_devices_t devices,
3722 audio_output_flags_t flags,
3723 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003724 struct audio_stream_out **stream_out,
3725 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726{
3727 struct audio_device *adev = (struct audio_device *)dev;
3728 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303729 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003730 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303733
3734 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3735 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003736 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303737 return -EINVAL;
3738 }
3739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3741
Mingming Yin3a941d42016-02-17 18:08:05 -08003742 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3743 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303744 devices, flags, &out->stream);
3745
3746
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003747 if (!out) {
3748 return -ENOMEM;
3749 }
3750
Haynes Mathew George204045b2015-02-25 20:32:03 -08003751 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003752 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003753 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 if (devices == AUDIO_DEVICE_NONE)
3756 devices = AUDIO_DEVICE_OUT_SPEAKER;
3757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 out->flags = flags;
3759 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003760 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003761 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 out->sample_rate = config->sample_rate;
3763 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3764 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003765 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003766 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003767 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303768 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
Mingming Yin3a941d42016-02-17 18:08:05 -08003770 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3771 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3772 pthread_mutex_lock(&adev->lock);
3773 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3774 ret = read_hdmi_sink_caps(out);
3775 pthread_mutex_unlock(&adev->lock);
3776 if (ret != 0) {
3777 if (ret == -ENOSYS) {
3778 /* ignore and go with default */
3779 ret = 0;
3780 } else {
3781 ALOGE("error reading hdmi sink caps");
3782 goto error_open;
3783 }
3784 }
3785 }
3786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003788 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303789 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3790 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003791 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3792 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3793
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003794 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003795 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3796 /*
3797 * Do not handle stereo output in Multi-channel cases
3798 * Stereo case is handled in normal playback path
3799 */
3800 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3801 ret = AUDIO_CHANNEL_OUT_STEREO;
3802 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003803
3804 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3805 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003806 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003807 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003808 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003809
3810 if (config->sample_rate == 0)
3811 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3812 if (config->channel_mask == 0)
3813 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003814 if (config->format == 0)
3815 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003816
3817 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003818 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003819 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3821 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003823 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003825 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3826 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003827 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003828 ret = voice_extn_compress_voip_open_output_stream(out);
3829 if (ret != 0) {
3830 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3831 __func__, ret);
3832 goto error_open;
3833 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003834 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3835 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3836
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3838 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3839 ALOGE("%s: Unsupported Offload information", __func__);
3840 ret = -EINVAL;
3841 goto error_open;
3842 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003843
Mingming Yin3a941d42016-02-17 18:08:05 -08003844 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003845 if(config->offload_info.format == 0)
3846 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003847 if (config->offload_info.sample_rate == 0)
3848 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003849 }
3850
Mingming Yin90310102013-11-13 16:57:00 -08003851 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303852 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003853 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003854 ret = -EINVAL;
3855 goto error_open;
3856 }
3857
3858 out->compr_config.codec = (struct snd_codec *)
3859 calloc(1, sizeof(struct snd_codec));
3860
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003861 if (!out->compr_config.codec) {
3862 ret = -ENOMEM;
3863 goto error_open;
3864 }
3865
vivek mehta0ea887a2015-08-26 14:01:20 -07003866 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303867 out->stream.pause = out_pause;
3868 out->stream.flush = out_flush;
3869 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003870 out->usecase = get_offload_usecase(adev, true);
3871 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003872 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003873 out->stream.set_callback = out_set_callback;
3874 out->stream.pause = out_pause;
3875 out->stream.resume = out_resume;
3876 out->stream.drain = out_drain;
3877 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003878 out->usecase = get_offload_usecase(adev, false);
3879 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003880 }
vivek mehta446c3962015-09-14 10:57:35 -07003881
3882 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003883 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3884 config->format == 0 && config->sample_rate == 0 &&
3885 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003886 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003887 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3888 } else {
3889 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3890 ret = -EEXIST;
3891 goto error_open;
3892 }
vivek mehta446c3962015-09-14 10:57:35 -07003893 }
3894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003895 if (config->offload_info.channel_mask)
3896 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003897 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003898 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003899 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003900 } else {
3901 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3902 ret = -EINVAL;
3903 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003904 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003905
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003906 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003907 out->sample_rate = config->offload_info.sample_rate;
3908
Mingming Yin3ee55c62014-08-04 14:23:35 -07003909 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303911 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3912 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3913 audio_extn_dolby_send_ddp_endp_params(adev);
3914 audio_extn_dolby_set_dmid(adev);
3915 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003917 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003918 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003919 out->compr_config.codec->bit_rate =
3920 config->offload_info.bit_rate;
3921 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303922 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003923 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303924 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003925 /*TODO: Do we need to change it for passthrough */
3926 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003927
Manish Dewangana6fc5442015-08-24 20:30:31 +05303928 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3929 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3930 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3931 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303932
3933 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3934 AUDIO_FORMAT_PCM) {
3935
3936 /*Based on platform support, configure appropriate alsa format for corresponding
3937 *hal input format.
3938 */
3939 out->compr_config.codec->format = hal_format_to_alsa(
3940 config->offload_info.format);
3941
Ashish Jain83a6cc22016-06-28 14:34:17 +05303942 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303943 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303944 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303945
3946 /*for direct PCM playback populate bit_width based on selected alsa format as
3947 *hal input format and alsa format might differ based on platform support.
3948 */
3949 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303950 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303951
3952 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3953
3954 /* Check if alsa session is configured with the same format as HAL input format,
3955 * if not then derive correct fragment size needed to accomodate the
3956 * conversion of HAL input format to alsa format.
3957 */
3958 audio_extn_utils_update_direct_pcm_fragment_size(out);
3959
3960 /*if hal input and output fragment size is different this indicates HAL input format is
3961 *not same as the alsa format
3962 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303963 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303964 /*Allocate a buffer to convert input data to the alsa configured format.
3965 *size of convert buffer is equal to the size required to hold one fragment size
3966 *worth of pcm data, this is because flinger does not write more than fragment_size
3967 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303968 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3969 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303970 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3971 ret = -ENOMEM;
3972 goto error_open;
3973 }
3974 }
3975 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3976 out->compr_config.fragment_size =
3977 audio_extn_passthru_get_buffer_size(&config->offload_info);
3978 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3979 } else {
3980 out->compr_config.fragment_size =
3981 platform_get_compress_offload_buffer_size(&config->offload_info);
3982 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3983 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003984
Amit Shekhar6f461b12014-08-01 14:52:58 -07003985 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303986 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3989 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003990
Alexy Josephaa54c872014-12-03 02:46:47 -08003991
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003992 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303993 out->send_next_track_params = false;
3994 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003995 out->offload_state = OFFLOAD_STATE_IDLE;
3996 out->playback_started = 0;
3997
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003998 audio_extn_dts_create_state_notifier_node(out->usecase);
3999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004000 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4001 __func__, config->offload_info.version,
4002 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304003
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304004 /* Check if DSD audio format is supported in codec
4005 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304006 */
4007
4008 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304009 (!platform_check_codec_dsd_support(adev->platform) ||
4010 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304011 ret = -EINVAL;
4012 goto error_open;
4013 }
4014
Ashish Jain5106d362016-05-11 19:23:33 +05304015 /* Disable gapless if any of the following is true
4016 * passthrough playback
4017 * AV playback
4018 * Direct PCM playback
4019 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304020 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304021 (config->format == AUDIO_FORMAT_DSD) ||
4022 config->offload_info.has_video ||
4023 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304024 check_and_set_gapless_mode(adev, false);
4025 } else
4026 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004027
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304028 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004029 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4030 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304031 if (config->format == AUDIO_FORMAT_DSD) {
4032 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4033 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4034 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004035
4036 create_offload_callback_thread(out);
4037
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004038 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304039 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004040 if (ret != 0) {
4041 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4042 __func__, ret);
4043 goto error_open;
4044 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004045 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4046 if (config->sample_rate == 0)
4047 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4048 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4049 config->sample_rate != 8000) {
4050 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4051 ret = -EINVAL;
4052 goto error_open;
4053 }
4054 out->sample_rate = config->sample_rate;
4055 out->config.rate = config->sample_rate;
4056 if (config->format == AUDIO_FORMAT_DEFAULT)
4057 config->format = AUDIO_FORMAT_PCM_16_BIT;
4058 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4059 config->format = AUDIO_FORMAT_PCM_16_BIT;
4060 ret = -EINVAL;
4061 goto error_open;
4062 }
4063 out->format = config->format;
4064 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4065 out->config = pcm_config_afe_proxy_playback;
4066 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004067 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304068 unsigned int channels = 0;
4069 /*Update config params to default if not set by the caller*/
4070 if (config->sample_rate == 0)
4071 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4072 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4073 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4074 if (config->format == AUDIO_FORMAT_DEFAULT)
4075 config->format = AUDIO_FORMAT_PCM_16_BIT;
4076
4077 channels = audio_channel_count_from_out_mask(out->channel_mask);
4078
Ashish Jain83a6cc22016-06-28 14:34:17 +05304079 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4080 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004081 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4082 out->flags);
4083 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304084 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4085 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4086 out->config = pcm_config_low_latency;
4087 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4088 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4089 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304090 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4091 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4092 if (out->config.period_size <= 0) {
4093 ALOGE("Invalid configuration period size is not valid");
4094 ret = -EINVAL;
4095 goto error_open;
4096 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304097 } else {
4098 /* primary path is the default path selected if no other outputs are available/suitable */
4099 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4100 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4101 }
4102 out->hal_ip_format = format = out->format;
4103 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4104 out->hal_op_format = pcm_format_to_hal(out->config.format);
4105 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4106 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004107 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304108 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304109 if (out->hal_ip_format != out->hal_op_format) {
4110 uint32_t buffer_size = out->config.period_size *
4111 format_to_bitwidth_table[out->hal_op_format] *
4112 out->config.channels;
4113 out->convert_buffer = calloc(1, buffer_size);
4114 if (out->convert_buffer == NULL){
4115 ALOGE("Allocation failed for convert buffer for size %d",
4116 out->compr_config.fragment_size);
4117 ret = -ENOMEM;
4118 goto error_open;
4119 }
4120 ALOGD("Convert buffer allocated of size %d", buffer_size);
4121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122 }
4123
Ashish Jain83a6cc22016-06-28 14:34:17 +05304124 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4125 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4126
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004127 /* TODO remove this hardcoding and check why width is zero*/
4128 if (out->bit_width == 0)
4129 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304130 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004131 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004132 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05304133 out->bit_width, out->channel_mask,
4134 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004135 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4136 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4137 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004138 if(adev->primary_output == NULL)
4139 adev->primary_output = out;
4140 else {
4141 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004142 ret = -EEXIST;
4143 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004144 }
4145 }
4146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 /* Check if this usecase is already existing */
4148 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004149 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4150 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004153 ret = -EEXIST;
4154 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 }
4156 pthread_mutex_unlock(&adev->lock);
4157
4158 out->stream.common.get_sample_rate = out_get_sample_rate;
4159 out->stream.common.set_sample_rate = out_set_sample_rate;
4160 out->stream.common.get_buffer_size = out_get_buffer_size;
4161 out->stream.common.get_channels = out_get_channels;
4162 out->stream.common.get_format = out_get_format;
4163 out->stream.common.set_format = out_set_format;
4164 out->stream.common.standby = out_standby;
4165 out->stream.common.dump = out_dump;
4166 out->stream.common.set_parameters = out_set_parameters;
4167 out->stream.common.get_parameters = out_get_parameters;
4168 out->stream.common.add_audio_effect = out_add_audio_effect;
4169 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4170 out->stream.get_latency = out_get_latency;
4171 out->stream.set_volume = out_set_volume;
4172 out->stream.write = out_write;
4173 out->stream.get_render_position = out_get_render_position;
4174 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004175 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004177 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004179 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004180 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181
4182 config->format = out->stream.common.get_format(&out->stream.common);
4183 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4184 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4185
4186 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304187 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004188 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004189
4190 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4191 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4192 popcount(out->channel_mask), out->playback_started);
4193
Eric Laurent994a6932013-07-17 11:51:42 -07004194 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004196
4197error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304198 if (out->convert_buffer)
4199 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004200 free(out);
4201 *stream_out = NULL;
4202 ALOGD("%s: exit: ret %d", __func__, ret);
4203 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204}
4205
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304206void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 struct audio_stream_out *stream)
4208{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004209 struct stream_out *out = (struct stream_out *)stream;
4210 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004211 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004212
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304213 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4214
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004215 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304216 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004217 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304218 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004219 if(ret != 0)
4220 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4221 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004222 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004223 out_standby(&stream->common);
4224
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004225 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004226 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004227 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004228 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004229 if (out->compr_config.codec != NULL)
4230 free(out->compr_config.codec);
4231 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004232
Ashish Jain83a6cc22016-06-28 14:34:17 +05304233 if (out->convert_buffer != NULL) {
4234 free(out->convert_buffer);
4235 out->convert_buffer = NULL;
4236 }
4237
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004238 if (adev->voice_tx_output == out)
4239 adev->voice_tx_output = NULL;
4240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004241 pthread_cond_destroy(&out->cond);
4242 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004244 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245}
4246
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004247static void close_compress_sessions(struct audio_device *adev)
4248{
Mingming Yin7b762e72015-03-04 13:47:32 -08004249 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304250 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004251 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004252 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304253
4254 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004255 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304256 if (is_offload_usecase(usecase->id)) {
4257 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004258 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4259 out = usecase->stream.out;
4260 pthread_mutex_unlock(&adev->lock);
4261 out_standby(&out->stream.common);
4262 pthread_mutex_lock(&adev->lock);
4263 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304264 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004265 }
4266 pthread_mutex_unlock(&adev->lock);
4267}
4268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4270{
4271 struct audio_device *adev = (struct audio_device *)dev;
4272 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004274 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004275 int ret;
4276 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004278 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304281 if (!parms)
4282 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004283 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4284 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304285 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304286 if (strstr(snd_card_status, "OFFLINE")) {
4287 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304288 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004289 //close compress sessions on OFFLINE status
4290 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304291 } else if (strstr(snd_card_status, "ONLINE")) {
4292 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304293 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004294 //send dts hpx license if enabled
4295 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304296 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304297 }
4298
4299 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004300 status = voice_set_parameters(adev, parms);
4301 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004302 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004304 status = platform_set_parameters(adev->platform, parms);
4305 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004306 goto done;
4307
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004308 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4309 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004310 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4312 adev->bluetooth_nrec = true;
4313 else
4314 adev->bluetooth_nrec = false;
4315 }
4316
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004317 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4318 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4320 adev->screen_off = false;
4321 else
4322 adev->screen_off = true;
4323 }
4324
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004325 ret = str_parms_get_int(parms, "rotation", &val);
4326 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004327 bool reverse_speakers = false;
4328 switch(val) {
4329 // FIXME: note that the code below assumes that the speakers are in the correct placement
4330 // relative to the user when the device is rotated 90deg from its default rotation. This
4331 // assumption is device-specific, not platform-specific like this code.
4332 case 270:
4333 reverse_speakers = true;
4334 break;
4335 case 0:
4336 case 90:
4337 case 180:
4338 break;
4339 default:
4340 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004341 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004342 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004343 if (status == 0) {
4344 if (adev->speaker_lr_swap != reverse_speakers) {
4345 adev->speaker_lr_swap = reverse_speakers;
4346 // only update the selected device if there is active pcm playback
4347 struct audio_usecase *usecase;
4348 struct listnode *node;
4349 list_for_each(node, &adev->usecase_list) {
4350 usecase = node_to_item(node, struct audio_usecase, list);
4351 if (usecase->type == PCM_PLAYBACK) {
4352 select_devices(adev, usecase->id);
4353 break;
4354 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004355 }
4356 }
4357 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004358 }
4359
Mingming Yin514a8bc2014-07-29 15:22:21 -07004360 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4361 if (ret >= 0) {
4362 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4363 adev->bt_wb_speech_enabled = true;
4364 else
4365 adev->bt_wb_speech_enabled = false;
4366 }
4367
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004368 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4369 if (ret >= 0) {
4370 val = atoi(value);
4371 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004372 ALOGV("cache new ext disp type and edid");
4373 ret = platform_get_ext_disp_type(adev->platform);
4374 if (ret < 0) {
4375 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004376 status = ret;
4377 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004378 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004379 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004380 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004381 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004382 /*
4383 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4384 * Per AudioPolicyManager, USB device is higher priority than WFD.
4385 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4386 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4387 * starting voice call on USB
4388 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004389 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4390 if (ret >= 0) {
4391 audio_extn_usb_add_device(val, atoi(value));
4392 }
vivek mehta344576a2016-04-12 18:56:03 -07004393 ALOGV("detected USB connect .. disable proxy");
4394 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004395 }
4396 }
4397
4398 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4399 if (ret >= 0) {
4400 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004401 /*
4402 * The HDMI / Displayport disconnect handling has been moved to
4403 * audio extension to ensure that its parameters are not
4404 * invalidated prior to updating sysfs of the disconnect event
4405 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4406 */
4407 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004408 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004409 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4410 if (ret >= 0) {
4411 audio_extn_usb_remove_device(val, atoi(value));
4412 }
vivek mehta344576a2016-04-12 18:56:03 -07004413 ALOGV("detected USB disconnect .. enable proxy");
4414 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004415 }
4416 }
4417
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304418 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4419 if (ret >= 0) {
4420 struct audio_usecase *usecase;
4421 struct listnode *node;
4422 list_for_each(node, &adev->usecase_list) {
4423 usecase = node_to_item(node, struct audio_usecase, list);
4424 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004425 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304426 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304427 lock_output_stream(usecase->stream.out);
4428 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304429 //force device switch to re configure encoder
4430 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304431 audio_extn_a2dp_set_handoff_mode(false);
4432 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304433 break;
4434 }
4435 }
4436 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304437 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004438done:
4439 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004440 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304441error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004442 ALOGV("%s: exit with code(%d)", __func__, status);
4443 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444}
4445
4446static char* adev_get_parameters(const struct audio_hw_device *dev,
4447 const char *keys)
4448{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004449 struct audio_device *adev = (struct audio_device *)dev;
4450 struct str_parms *reply = str_parms_create();
4451 struct str_parms *query = str_parms_create_str(keys);
4452 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304453 char value[256] = {0};
4454 int ret = 0;
4455
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004456 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004457 if (reply) {
4458 str_parms_destroy(reply);
4459 }
4460 if (query) {
4461 str_parms_destroy(query);
4462 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004463 ALOGE("adev_get_parameters: failed to create query or reply");
4464 return NULL;
4465 }
4466
Naresh Tannirud7205b62014-06-20 02:54:48 +05304467 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4468 sizeof(value));
4469 if (ret >=0) {
4470 int val = 1;
4471 pthread_mutex_lock(&adev->snd_card_status.lock);
4472 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4473 val = 0;
4474 pthread_mutex_unlock(&adev->snd_card_status.lock);
4475 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4476 goto exit;
4477 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004478
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004479 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004480 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004481 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004482 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304483 pthread_mutex_unlock(&adev->lock);
4484
Naresh Tannirud7205b62014-06-20 02:54:48 +05304485exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004486 str = str_parms_to_str(reply);
4487 str_parms_destroy(query);
4488 str_parms_destroy(reply);
4489
4490 ALOGV("%s: exit: returns - %s", __func__, str);
4491 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492}
4493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004494static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495{
4496 return 0;
4497}
4498
4499static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4500{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004501 int ret;
4502 struct audio_device *adev = (struct audio_device *)dev;
4503 pthread_mutex_lock(&adev->lock);
4504 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004505 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004506 pthread_mutex_unlock(&adev->lock);
4507 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508}
4509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004510static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4511 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512{
4513 return -ENOSYS;
4514}
4515
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004516static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4517 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518{
4519 return -ENOSYS;
4520}
4521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004522static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4523 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524{
4525 return -ENOSYS;
4526}
4527
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004528static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4529 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530{
4531 return -ENOSYS;
4532}
4533
4534static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4535{
4536 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 pthread_mutex_lock(&adev->lock);
4539 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004540 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004542 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004543 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004544 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004545 adev->current_call_output = NULL;
4546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547 }
4548 pthread_mutex_unlock(&adev->lock);
4549 return 0;
4550}
4551
4552static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4553{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004554 int ret;
4555
4556 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004557 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004558 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4559 pthread_mutex_unlock(&adev->lock);
4560
4561 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562}
4563
4564static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4565{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004566 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 return 0;
4568}
4569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004570static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 const struct audio_config *config)
4572{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004573 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004575 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4576 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577}
4578
4579static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004580 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 audio_devices_t devices,
4582 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004583 struct audio_stream_in **stream_in,
4584 audio_input_flags_t flags __unused,
4585 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004586 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587{
4588 struct audio_device *adev = (struct audio_device *)dev;
4589 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004590 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004591 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004592 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304593 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304596 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4597 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304599 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004600
4601 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004602
4603 if (!in) {
4604 ALOGE("failed to allocate input stream");
4605 return -ENOMEM;
4606 }
4607
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304608 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304609 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4610 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004611 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004612 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 in->stream.common.get_sample_rate = in_get_sample_rate;
4615 in->stream.common.set_sample_rate = in_set_sample_rate;
4616 in->stream.common.get_buffer_size = in_get_buffer_size;
4617 in->stream.common.get_channels = in_get_channels;
4618 in->stream.common.get_format = in_get_format;
4619 in->stream.common.set_format = in_set_format;
4620 in->stream.common.standby = in_standby;
4621 in->stream.common.dump = in_dump;
4622 in->stream.common.set_parameters = in_set_parameters;
4623 in->stream.common.get_parameters = in_get_parameters;
4624 in->stream.common.add_audio_effect = in_add_audio_effect;
4625 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4626 in->stream.set_gain = in_set_gain;
4627 in->stream.read = in_read;
4628 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4629
4630 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004631 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 in->standby = 1;
4634 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004635 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004636 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637
4638 /* Update config params with the requested sample rate and channels */
4639 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004640 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4641 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4642 is_low_latency = true;
4643#if LOW_LATENCY_CAPTURE_USE_CASE
4644 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4645#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004646 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004647 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004648
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004649 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004650 if (in->realtime) {
4651 in->config = pcm_config_audio_capture_rt;
4652 in->sample_rate = in->config.rate;
4653 in->af_period_multiplier = af_period_multiplier;
4654 } else {
4655 in->config = pcm_config_audio_capture;
4656 in->config.rate = config->sample_rate;
4657 in->sample_rate = config->sample_rate;
4658 in->af_period_multiplier = 1;
4659 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304660 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004662 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304663 if (adev->mode != AUDIO_MODE_IN_CALL) {
4664 ret = -EINVAL;
4665 goto err_open;
4666 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004667 if (config->sample_rate == 0)
4668 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4669 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4670 config->sample_rate != 8000) {
4671 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4672 ret = -EINVAL;
4673 goto err_open;
4674 }
4675 if (config->format == AUDIO_FORMAT_DEFAULT)
4676 config->format = AUDIO_FORMAT_PCM_16_BIT;
4677 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4678 config->format = AUDIO_FORMAT_PCM_16_BIT;
4679 ret = -EINVAL;
4680 goto err_open;
4681 }
4682
4683 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4684 in->config = pcm_config_afe_proxy_record;
4685 in->config.channels = channel_count;
4686 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304687 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304688 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4689 in, config, &channel_mask_updated)) {
4690 if (channel_mask_updated == true) {
4691 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4692 __func__, config->channel_mask);
4693 ret = -EINVAL;
4694 goto err_open;
4695 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304696 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004697 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004698 audio_extn_compr_cap_format_supported(config->format) &&
4699 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004700 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004701 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304702 /* restrict 24 bit capture for unprocessed source only
4703 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4704 */
4705 if (config->format == AUDIO_FORMAT_DEFAULT) {
4706 config->format = AUDIO_FORMAT_PCM_16_BIT;
4707 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4708 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4709 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4710 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4711 bool ret_error = false;
4712 in->bit_width = 24;
4713 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4714 from HAL is 24_packed and 8_24
4715 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4716 24_packed return error indicating supported format is 24_packed
4717 *> In case of any other source requesting 24 bit or float return error
4718 indicating format supported is 16 bit only.
4719
4720 on error flinger will retry with supported format passed
4721 */
4722 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4723 (source != AUDIO_SOURCE_CAMCORDER)) {
4724 config->format = AUDIO_FORMAT_PCM_16_BIT;
4725 if( config->sample_rate > 48000)
4726 config->sample_rate = 48000;
4727 ret_error = true;
4728 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4729 in->config.format = PCM_FORMAT_S24_3LE;
4730 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4731 in->config.format = PCM_FORMAT_S24_LE;
4732 } else {
4733 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4734 ret_error = true;
4735 }
4736
4737 if (ret_error) {
4738 ret = -EINVAL;
4739 goto err_open;
4740 }
4741 }
4742
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004743 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004744 if (!in->realtime) {
4745 in->format = config->format;
4746 frame_size = audio_stream_in_frame_size(&in->stream);
4747 buffer_size = get_input_buffer_size(config->sample_rate,
4748 config->format,
4749 channel_count,
4750 is_low_latency);
4751 in->config.period_size = buffer_size / frame_size;
4752 }
4753
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004754 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4755 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4756 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004757 (in->config.rate == 8000 || in->config.rate == 16000 ||
4758 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004759 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4760 voice_extn_compress_voip_open_input_stream(in);
4761 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004762 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304764 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4765 &adev->streams_input_cfg_list,
4766 devices, flags, in->format, in->sample_rate,
4767 in->bit_width, &in->app_type_cfg);
4768
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004769 /* This stream could be for sound trigger lab,
4770 get sound trigger pcm if present */
4771 audio_extn_sound_trigger_check_and_get_session(in);
4772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004774 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776
4777err_open:
4778 free(in);
4779 *stream_in = NULL;
4780 return ret;
4781}
4782
4783static void adev_close_input_stream(struct audio_hw_device *dev,
4784 struct audio_stream_in *stream)
4785{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004786 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004787 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004788 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304789
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304790 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004791
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304792 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004793 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304794
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004795 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304796 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004797 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304798 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004799 if (ret != 0)
4800 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4801 __func__, ret);
4802 } else
4803 in_standby(&stream->common);
4804
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004805 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004806 audio_extn_ssr_deinit();
4807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808
Mingming Yine62d7842013-10-25 16:26:03 -07004809 if(audio_extn_compr_cap_enabled() &&
4810 audio_extn_compr_cap_format_supported(in->config.format))
4811 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004812
Mingming Yinfd7607b2016-01-22 12:48:44 -08004813 if (in->is_st_session) {
4814 ALOGV("%s: sound trigger pcm stop lab", __func__);
4815 audio_extn_sound_trigger_stop_lab(in);
4816 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004817 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 return;
4819}
4820
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004821static int adev_dump(const audio_hw_device_t *device __unused,
4822 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823{
4824 return 0;
4825}
4826
4827static int adev_close(hw_device_t *device)
4828{
4829 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004830
4831 if (!adev)
4832 return 0;
4833
4834 pthread_mutex_lock(&adev_init_lock);
4835
4836 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004837 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004838 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304839 audio_extn_utils_release_streams_cfg_lists(
4840 &adev->streams_output_cfg_list,
4841 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304842 if (audio_extn_qaf_is_enabled())
4843 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004844 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004845 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004846 free(adev->snd_dev_ref_cnt);
4847 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004848 if (adev->adm_deinit)
4849 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004850 free(device);
4851 adev = NULL;
4852 }
4853 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 return 0;
4856}
4857
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004858/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4859 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4860 * just that it _might_ work.
4861 */
4862static int period_size_is_plausible_for_low_latency(int period_size)
4863{
4864 switch (period_size) {
4865 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004866 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004867 case 240:
4868 case 320:
4869 case 480:
4870 return 1;
4871 default:
4872 return 0;
4873 }
4874}
4875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876static int adev_open(const hw_module_t *module, const char *name,
4877 hw_device_t **device)
4878{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304879 int ret;
4880
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004881 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4883
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004884 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004885 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004886 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004887 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004888 ALOGD("%s: returning existing instance of adev", __func__);
4889 ALOGD("%s: exit", __func__);
4890 pthread_mutex_unlock(&adev_init_lock);
4891 return 0;
4892 }
4893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 adev = calloc(1, sizeof(struct audio_device));
4895
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004896 if (!adev) {
4897 pthread_mutex_unlock(&adev_init_lock);
4898 return -ENOMEM;
4899 }
4900
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004901 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4904 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4905 adev->device.common.module = (struct hw_module_t *)module;
4906 adev->device.common.close = adev_close;
4907
4908 adev->device.init_check = adev_init_check;
4909 adev->device.set_voice_volume = adev_set_voice_volume;
4910 adev->device.set_master_volume = adev_set_master_volume;
4911 adev->device.get_master_volume = adev_get_master_volume;
4912 adev->device.set_master_mute = adev_set_master_mute;
4913 adev->device.get_master_mute = adev_get_master_mute;
4914 adev->device.set_mode = adev_set_mode;
4915 adev->device.set_mic_mute = adev_set_mic_mute;
4916 adev->device.get_mic_mute = adev_get_mic_mute;
4917 adev->device.set_parameters = adev_set_parameters;
4918 adev->device.get_parameters = adev_get_parameters;
4919 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4920 adev->device.open_output_stream = adev_open_output_stream;
4921 adev->device.close_output_stream = adev_close_output_stream;
4922 adev->device.open_input_stream = adev_open_input_stream;
4923 adev->device.close_input_stream = adev_close_input_stream;
4924 adev->device.dump = adev_dump;
4925
4926 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004928 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004929 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004932 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004933 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004934 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004935 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004936 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004937 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004938 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004939 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304940 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304941 adev->perf_lock_opts[0] = 0x101;
4942 adev->perf_lock_opts[1] = 0x20E;
4943 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304944
4945 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4946 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004948 adev->platform = platform_init(adev);
4949 if (!adev->platform) {
4950 free(adev->snd_dev_ref_cnt);
4951 free(adev);
4952 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4953 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004954 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304955 pthread_mutex_destroy(&adev->lock);
4956 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004957 return -EINVAL;
4958 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004959
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304960 if (audio_extn_qaf_is_enabled()) {
4961 ret = audio_extn_qaf_init(adev);
4962 if (ret < 0) {
4963 free(adev);
4964 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4965 *device = NULL;
4966 pthread_mutex_unlock(&adev_init_lock);
4967 pthread_mutex_destroy(&adev->lock);
4968 return ret;
4969 }
4970
4971 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4972 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4973 }
4974
Naresh Tanniru4c630392014-05-12 01:05:52 +05304975 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4976
Eric Laurentc4aef752013-09-12 17:45:53 -07004977 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4978 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4979 if (adev->visualizer_lib == NULL) {
4980 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4981 } else {
4982 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4983 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004984 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004985 "visualizer_hal_start_output");
4986 adev->visualizer_stop_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_stop_output");
4989 }
4990 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004991 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004992 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004993 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004994
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004995 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4996 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4997 if (adev->offload_effects_lib == NULL) {
4998 ALOGE("%s: DLOPEN failed for %s", __func__,
4999 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5000 } else {
5001 ALOGV("%s: DLOPEN successful for %s", __func__,
5002 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5003 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305004 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005005 "offload_effects_bundle_hal_start_output");
5006 adev->offload_effects_stop_output =
5007 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5008 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005009 adev->offload_effects_set_hpx_state =
5010 (int (*)(bool))dlsym(adev->offload_effects_lib,
5011 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305012 adev->offload_effects_get_parameters =
5013 (void (*)(struct str_parms *, struct str_parms *))
5014 dlsym(adev->offload_effects_lib,
5015 "offload_effects_bundle_get_parameters");
5016 adev->offload_effects_set_parameters =
5017 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5018 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005019 }
5020 }
5021
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005022 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5023 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5024 if (adev->adm_lib == NULL) {
5025 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5026 } else {
5027 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5028 adev->adm_init = (adm_init_t)
5029 dlsym(adev->adm_lib, "adm_init");
5030 adev->adm_deinit = (adm_deinit_t)
5031 dlsym(adev->adm_lib, "adm_deinit");
5032 adev->adm_register_input_stream = (adm_register_input_stream_t)
5033 dlsym(adev->adm_lib, "adm_register_input_stream");
5034 adev->adm_register_output_stream = (adm_register_output_stream_t)
5035 dlsym(adev->adm_lib, "adm_register_output_stream");
5036 adev->adm_deregister_stream = (adm_deregister_stream_t)
5037 dlsym(adev->adm_lib, "adm_deregister_stream");
5038 adev->adm_request_focus = (adm_request_focus_t)
5039 dlsym(adev->adm_lib, "adm_request_focus");
5040 adev->adm_abandon_focus = (adm_abandon_focus_t)
5041 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005042 adev->adm_set_config = (adm_set_config_t)
5043 dlsym(adev->adm_lib, "adm_set_config");
5044 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5045 dlsym(adev->adm_lib, "adm_request_focus_v2");
5046 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5047 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5048 adev->adm_on_routing_change = (adm_on_routing_change_t)
5049 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005050 }
5051 }
5052
Mingming Yin514a8bc2014-07-29 15:22:21 -07005053 adev->bt_wb_speech_enabled = false;
5054
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005055 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 *device = &adev->device.common;
5057
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305058 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5059 &adev->streams_output_cfg_list,
5060 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005061
Kiran Kandi910e1862013-10-29 13:29:42 -07005062 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005063
5064 char value[PROPERTY_VALUE_MAX];
5065 int trial;
5066 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5067 trial = atoi(value);
5068 if (period_size_is_plausible_for_low_latency(trial)) {
5069 pcm_config_low_latency.period_size = trial;
5070 pcm_config_low_latency.start_threshold = trial / 4;
5071 pcm_config_low_latency.avail_min = trial / 4;
5072 configured_low_latency_capture_period_size = trial;
5073 }
5074 }
5075 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5076 trial = atoi(value);
5077 if (period_size_is_plausible_for_low_latency(trial)) {
5078 configured_low_latency_capture_period_size = trial;
5079 }
5080 }
5081
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005082 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5083 af_period_multiplier = atoi(value);
5084 if (af_period_multiplier < 0)
5085 af_period_multiplier = 2;
5086 else if (af_period_multiplier > 4)
5087 af_period_multiplier = 4;
5088
5089 ALOGV("new period_multiplier = %d", af_period_multiplier);
5090 }
5091
vivek mehta446c3962015-09-14 10:57:35 -07005092 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005093 pthread_mutex_unlock(&adev_init_lock);
5094
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005095 if (adev->adm_init)
5096 adev->adm_data = adev->adm_init();
5097
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305098 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005099 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 return 0;
5101}
5102
5103static struct hw_module_methods_t hal_module_methods = {
5104 .open = adev_open,
5105};
5106
5107struct audio_module HAL_MODULE_INFO_SYM = {
5108 .common = {
5109 .tag = HARDWARE_MODULE_TAG,
5110 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5111 .hal_api_version = HARDWARE_HAL_API_VERSION,
5112 .id = AUDIO_HARDWARE_MODULE_ID,
5113 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005114 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 .methods = &hal_module_methods,
5116 },
5117};