blob: 673c17e5562b47516170e5373c847d31d3042ff3 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625/*
626 * Enable ASRC mode if native or DSD stream is active.
627 */
628static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
629{
630 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635
636 list_for_each(node, &adev->usecase_list) {
637 uc = node_to_item(node, struct audio_usecase, list);
638 curr_out = (struct stream_out*) uc->stream.out;
639
640 if (curr_out && PCM_PLAYBACK == uc->type) {
641 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
642 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
643 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
644 __func__);
645 audio_route_apply_and_update_path(adev->audio_route,
646 "asrc-mode");
647 adev->asrc_mode_enabled = true;
648 break;
649 }
650 }
651 }
652 }
653}
654
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700655int pcm_ioctl(struct pcm *pcm, int request, ...)
656{
657 va_list ap;
658 void * arg;
659 int pcm_fd = *(int*)pcm;
660
661 va_start(ap, request);
662 arg = va_arg(ap, void *);
663 va_end(ap);
664
665 return ioctl(pcm_fd, request, arg);
666}
667
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700668int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700672 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800673
674 if (usecase == NULL)
675 return -EINVAL;
676
677 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
678
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800684#ifdef DS1_DOLBY_DAP_ENABLED
685 audio_extn_dolby_set_dmid(adev);
686 audio_extn_dolby_set_endpoint(adev);
687#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700688 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700689 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530690 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700691 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530692 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800693 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700694 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700695 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700696 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 ALOGV("%s: exit", __func__);
698 return 0;
699}
700
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700701int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530707 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 if (usecase->type == PCM_CAPTURE)
712 snd_device = usecase->in_snd_device;
713 else
714 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800715 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700716 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700717 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700719 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530720 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 ALOGV("%s: exit", __func__);
722 return 0;
723}
724
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700725int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530728 int i, num_devices = 0;
729 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700730 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
731
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800732 if (snd_device < SND_DEVICE_MIN ||
733 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800734 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800735 return -EINVAL;
736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737
738 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700739
740 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
741 ALOGE("%s: Invalid sound device returned", __func__);
742 return -EINVAL;
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700745 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700746 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 return 0;
748 }
749
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530750
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700751 if (audio_extn_spkr_prot_is_enabled())
752 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800754 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
755 audio_extn_spkr_prot_is_enabled()) {
756 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700757 adev->snd_dev_ref_cnt[snd_device]--;
758 return -EINVAL;
759 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200760 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800761 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800762 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200763 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 return -EINVAL;
765 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530766 } else if (platform_can_split_snd_device(adev->platform, snd_device,
767 &num_devices, new_snd_devices)) {
768 for (i = 0; i < num_devices; i++) {
769 enable_snd_device(adev, new_snd_devices[i]);
770 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530773
774 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
775 (audio_extn_a2dp_start_playback() < 0)) {
776 ALOGE(" fail to configure A2dp control path ");
777 return -EINVAL;
778 }
779
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700780 /* due to the possibility of calibration overwrite between listen
781 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700782 audio_extn_sound_trigger_update_device_status(snd_device,
783 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530784 audio_extn_listen_update_device_status(snd_device,
785 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700786 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 audio_extn_sound_trigger_update_device_status(snd_device,
789 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530790 audio_extn_listen_update_device_status(snd_device,
791 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700792 return -EINVAL;
793 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300794 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
797 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
798 !adev->native_playback_enabled &&
799 audio_is_true_native_stream_active(adev)) {
800 ALOGD("%s: %d: napb: enabling native mode in hardware",
801 __func__, __LINE__);
802 audio_route_apply_and_update_path(adev->audio_route,
803 "true-native-mode");
804 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530805 } else
806 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530814 int i, num_devices = 0;
815 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 if (snd_device < SND_DEVICE_MIN ||
819 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 return -EINVAL;
822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
824 ALOGE("%s: device ref cnt is already 0", __func__);
825 return -EINVAL;
826 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700829
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
831 ALOGE("%s: Invalid sound device returned", __func__);
832 return -EINVAL;
833 }
834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700836 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530837
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800838 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
839 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700840 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530841 } else if (platform_can_split_snd_device(adev->platform, snd_device,
842 &num_devices, new_snd_devices)) {
843 for (i = 0; i < num_devices; i++) {
844 disable_snd_device(adev, new_snd_devices[i]);
845 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300846 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700847 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300848 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700849
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530850 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
851 audio_extn_a2dp_stop_playback();
852
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700853 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530855 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 adev->native_playback_enabled) {
857 ALOGD("%s: %d: napb: disabling native mode in hardware",
858 __func__, __LINE__);
859 audio_route_reset_and_update_path(adev->audio_route,
860 "true-native-mode");
861 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530862 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
863 adev->asrc_mode_enabled) {
864 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
865 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
866 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530868
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200869 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700870 audio_extn_sound_trigger_update_device_status(snd_device,
871 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530872 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800873 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 return 0;
877}
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530880 struct audio_usecase *uc_info,
881 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882{
883 struct listnode *node;
884 struct audio_usecase *usecase;
885 bool switch_device[AUDIO_USECASE_MAX];
886 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530887 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 /*
889 * This function is to make sure that all the usecases that are active on
890 * the hardware codec backend are always routed to any one device that is
891 * handled by the hardware codec.
892 * For example, if low-latency and deep-buffer usecases are currently active
893 * on speaker and out_set_parameters(headset) is received on low-latency
894 * output, then we have to make sure deep-buffer is also switched to headset,
895 * because of the limitation that both the devices cannot be enabled
896 * at the same time as they share the same backend.
897 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700898 /*
899 * This call is to check if we need to force routing for a particular stream
900 * If there is a backend configuration change for the device when a
901 * new stream starts, then ADM needs to be closed and re-opened with the new
902 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800903 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700904 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800905 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
906 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
912 audio_extn_a2dp_is_force_device_switch()) {
913 force_routing = true;
914 force_restart_session = true;
915 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 ALOGD("%s:becf: force routing %d", __func__, force_routing);
917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800919 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 for (i = 0; i < AUDIO_USECASE_MAX; i++)
922 switch_device[i] = false;
923
924 list_for_each(node, &adev->usecase_list) {
925 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800926
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530927 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
928 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530929 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530930 platform_get_snd_device_name(usecase->out_snd_device),
931 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800932 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530933 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530934 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530935 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
936 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530937 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530938 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530939 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
940 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
941 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530942 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
944 platform_get_snd_device_name(usecase->out_snd_device));
945 disable_audio_route(adev, usecase);
946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530951 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
952 num_uc_to_switch);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700955 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530957 /* Make sure the previous devices to be disabled first and then enable the
958 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 }
964 }
965
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700970 }
971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 /* Re-route all the usecases on the shared backend other than the
974 specified usecase to new snd devices */
975 list_for_each(node, &adev->usecase_list) {
976 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530977 /* Update the out_snd_device only before enabling the audio route */
978 if (switch_device[usecase->id]) {
979 usecase->out_snd_device = snd_device;
980 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530981 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530982 use_case_table[usecase->id],
983 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989}
990
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530991static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 struct audio_usecase *uc_info,
993 snd_device_t snd_device)
994{
995 struct listnode *node;
996 struct audio_usecase *usecase;
997 bool switch_device[AUDIO_USECASE_MAX];
998 int i, num_uc_to_switch = 0;
999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301000 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1001 snd_device);
1002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001018 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301020 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001021 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301022 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001023 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001024 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001025 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1026 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001027 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001029 switch_device[usecase->id] = true;
1030 num_uc_to_switch++;
1031 }
1032 }
1033
1034 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001035 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301037 /* Make sure the previous devices to be disabled first and then enable the
1038 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001043 }
1044 }
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001049 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 }
1051 }
1052
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001053 /* Re-route all the usecases on the shared backend other than the
1054 specified usecase to new snd devices */
1055 list_for_each(node, &adev->usecase_list) {
1056 usecase = node_to_item(node, struct audio_usecase, list);
1057 /* Update the in_snd_device only before enabling the audio route */
1058 if (switch_device[usecase->id] ) {
1059 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001060 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301061 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001064 }
1065}
1066
Mingming Yin3a941d42016-02-17 18:08:05 -08001067static void reset_hdmi_sink_caps(struct stream_out *out) {
1068 int i = 0;
1069
1070 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1071 out->supported_channel_masks[i] = 0;
1072 }
1073 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1074 out->supported_formats[i] = 0;
1075 }
1076 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1077 out->supported_sample_rates[i] = 0;
1078 }
1079}
1080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001082static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083{
Mingming Yin3a941d42016-02-17 18:08:05 -08001084 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001085 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Mingming Yin3a941d42016-02-17 18:08:05 -08001087 reset_hdmi_sink_caps(out);
1088
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001089 /* Cache ext disp type */
1090 ret = platform_get_ext_disp_type(adev->platform);
1091 if (ret < 0) {
1092 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1093 return ret;
1094 }
1095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001098 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1101 case 6:
1102 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1103 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1104 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1105 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1107 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 break;
1109 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001110 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001111 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 break;
1113 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001114
1115 // check channel format caps
1116 i = 0;
1117 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1118 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1119 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1120 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1121 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1122 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1123 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1124 }
1125
1126 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1127 ALOGV(":%s HDMI supports DTS format", __func__);
1128 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1129 }
1130
1131 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1132 ALOGV(":%s HDMI supports DTS HD format", __func__);
1133 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1134 }
1135
1136
1137 // check sample rate caps
1138 i = 0;
1139 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1140 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1141 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1142 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1143 }
1144 }
1145
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147}
1148
Alexy Josephb1379942016-01-29 15:49:38 -08001149audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151{
1152 struct audio_usecase *usecase;
1153 struct listnode *node;
1154
1155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001157 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001158 ALOGV("%s: usecase id %d", __func__, usecase->id);
1159 return usecase->id;
1160 }
1161 }
1162 return USECASE_INVALID;
1163}
1164
Alexy Josephb1379942016-01-29 15:49:38 -08001165struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001166 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167{
1168 struct audio_usecase *usecase;
1169 struct listnode *node;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->id == uc_id)
1174 return usecase;
1175 }
1176 return NULL;
1177}
1178
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179/*
1180 * is a true native playback active
1181 */
1182bool audio_is_true_native_stream_active(struct audio_device *adev)
1183{
1184 bool active = false;
1185 int i = 0;
1186 struct listnode *node;
1187
1188 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1189 ALOGV("%s:napb: not in true mode or non hdphones device",
1190 __func__);
1191 active = false;
1192 goto exit;
1193 }
1194
1195 list_for_each(node, &adev->usecase_list) {
1196 struct audio_usecase *uc;
1197 uc = node_to_item(node, struct audio_usecase, list);
1198 struct stream_out *curr_out =
1199 (struct stream_out*) uc->stream.out;
1200
1201 if (curr_out && PCM_PLAYBACK == uc->type) {
1202 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1203 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1204 uc->id, curr_out->sample_rate,
1205 curr_out->bit_width,
1206 platform_get_snd_device_name(uc->out_snd_device));
1207
1208 if (is_offload_usecase(uc->id) &&
1209 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1210 active = true;
1211 ALOGD("%s:napb:native stream detected", __func__);
1212 }
1213 }
1214 }
1215exit:
1216 return active;
1217}
1218
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301219/*
1220 * if native DSD playback active
1221 */
1222bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1223{
1224 bool active = false;
1225 struct listnode *node = NULL;
1226 struct audio_usecase *uc = NULL;
1227 struct stream_out *curr_out = NULL;
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 uc = node_to_item(node, struct audio_usecase, list);
1231 curr_out = (struct stream_out*) uc->stream.out;
1232
1233 if (curr_out && PCM_PLAYBACK == uc->type &&
1234 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1235 active = true;
1236 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301237 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301238 }
1239 }
1240 return active;
1241}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301242
1243static bool force_device_switch(struct audio_usecase *usecase)
1244{
1245 bool ret = false;
1246 bool is_it_true_mode = false;
1247
1248 if (is_offload_usecase(usecase->id) &&
1249 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001250 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1251 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1252 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301253 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1254 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1255 (!is_it_true_mode && adev->native_playback_enabled)){
1256 ret = true;
1257 ALOGD("napb: time to toggle native mode");
1258 }
1259 }
1260
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301261 // Force all a2dp output devices to reconfigure for proper AFE encode format
1262 if((usecase->stream.out) &&
1263 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1264 audio_extn_a2dp_is_force_device_switch()) {
1265 ALOGD("Force a2dp device switch to update new encoder config");
1266 ret = true;
1267 }
1268
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301269 return ret;
1270}
1271
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001272int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001274 snd_device_t out_snd_device = SND_DEVICE_NONE;
1275 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276 struct audio_usecase *usecase = NULL;
1277 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001278 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001279 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001280 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301283 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1284
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001285 usecase = get_usecase_from_list(adev, uc_id);
1286 if (usecase == NULL) {
1287 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1288 return -EINVAL;
1289 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001291 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001292 (usecase->type == VOIP_CALL) ||
1293 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001294 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001295 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001296 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001297 usecase->devices = usecase->stream.out->devices;
1298 } else {
1299 /*
1300 * If the voice call is active, use the sound devices of voice call usecase
1301 * so that it would not result any device switch. All the usecases will
1302 * be switched to new device when select_devices() is called for voice call
1303 * usecase. This is to avoid switching devices for voice call when
1304 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001305 * choose voice call device only if the use case device is
1306 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001307 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001308 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001309 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001310 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001311 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1312 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301313 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1314 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001315 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 in_snd_device = vc_usecase->in_snd_device;
1317 out_snd_device = vc_usecase->out_snd_device;
1318 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001319 } else if (voice_extn_compress_voip_is_active(adev)) {
1320 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001321 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001322 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1323 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001324 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001325 in_snd_device = voip_usecase->in_snd_device;
1326 out_snd_device = voip_usecase->out_snd_device;
1327 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001328 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001329 hfp_ucid = audio_extn_hfp_get_usecase();
1330 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001331 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001332 in_snd_device = hfp_usecase->in_snd_device;
1333 out_snd_device = hfp_usecase->out_snd_device;
1334 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335 }
1336 if (usecase->type == PCM_PLAYBACK) {
1337 usecase->devices = usecase->stream.out->devices;
1338 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001339 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001340 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001341 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001342 if (usecase->stream.out == adev->primary_output &&
1343 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001344 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001345 select_devices(adev, adev->active_input->usecase);
1346 }
1347 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001348 } else if (usecase->type == PCM_CAPTURE) {
1349 usecase->devices = usecase->stream.in->device;
1350 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001352 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001353 if (adev->active_input &&
1354 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301355 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1356 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1357 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001358 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001359 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001360 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1361 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001362 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001363 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001364 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365 }
1366 }
1367
1368 if (out_snd_device == usecase->out_snd_device &&
1369 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301370
1371 if (!force_device_switch(usecase))
1372 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 }
1374
sangwoobc677242013-08-08 16:53:43 +09001375 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001376 out_snd_device, platform_get_snd_device_name(out_snd_device),
1377 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 /*
1380 * Limitation: While in call, to do a device switch we need to disable
1381 * and enable both RX and TX devices though one of them is same as current
1382 * device.
1383 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001384 if ((usecase->type == VOICE_CALL) &&
1385 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1386 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001387 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001388 }
1389
1390 if (((usecase->type == VOICE_CALL) ||
1391 (usecase->type == VOIP_CALL)) &&
1392 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1393 /* Disable sidetone only if voice/voip call already exists */
1394 if (voice_is_call_state_active(adev) ||
1395 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001396 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001397 }
1398
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001399 /* Disable current sound devices */
1400 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001401 disable_audio_route(adev, usecase);
1402 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 }
1404
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001405 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001406 disable_audio_route(adev, usecase);
1407 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408 }
1409
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001410 /* Applicable only on the targets that has external modem.
1411 * New device information should be sent to modem before enabling
1412 * the devices to reduce in-call device switch time.
1413 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001414 if ((usecase->type == VOICE_CALL) &&
1415 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1416 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001417 status = platform_switch_voice_call_enable_device_config(adev->platform,
1418 out_snd_device,
1419 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001420 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001421
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001422 /* Enable new sound devices */
1423 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001424 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001425 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426 }
1427
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001428 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301429 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001430 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001431 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432
Avinash Vaish71a8b972014-07-24 15:36:33 +05301433 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001434 status = platform_switch_voice_call_device_post(adev->platform,
1435 out_snd_device,
1436 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301437 enable_audio_route_for_voice_usecases(adev, usecase);
1438 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001439
sangwoo170731f2013-06-08 15:36:36 +09001440 usecase->in_snd_device = in_snd_device;
1441 usecase->out_snd_device = out_snd_device;
1442
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301443 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001444 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301445 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001446 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301447 usecase->stream.out->flags,
1448 usecase->stream.out->format,
1449 usecase->stream.out->sample_rate,
1450 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301451 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301452 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001453 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001454
1455 /* Notify device change info to effect clients registered */
1456 audio_extn_gef_notify_device_config(
1457 usecase->stream.out->devices,
1458 usecase->stream.out->channel_mask,
1459 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301460 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001461
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001463
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001464 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1465 /* Enable sidetone only if other voice/voip call already exists */
1466 if (voice_is_call_state_active(adev) ||
1467 voice_extn_compress_voip_is_started(adev))
1468 voice_set_sidetone(adev, out_snd_device, true);
1469 }
1470
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001471 /* Applicable only on the targets that has external modem.
1472 * Enable device command should be sent to modem only after
1473 * enabling voice call mixer controls
1474 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001475 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001476 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1477 out_snd_device,
1478 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301479 ALOGD("%s: done",__func__);
1480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 return status;
1482}
1483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484static int stop_input_stream(struct stream_in *in)
1485{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301486 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 struct audio_usecase *uc_info;
1488 struct audio_device *adev = in->dev;
1489
Eric Laurentc8400632013-02-14 19:04:54 -08001490 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Eric Laurent994a6932013-07-17 11:51:42 -07001492 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 uc_info = get_usecase_from_list(adev, in->usecase);
1495 if (uc_info == NULL) {
1496 ALOGE("%s: Could not find the usecase (%d) in the list",
1497 __func__, in->usecase);
1498 return -EINVAL;
1499 }
1500
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001501 /* Close in-call recording streams */
1502 voice_check_and_stop_incall_rec_usecase(adev, in);
1503
Eric Laurent150dbfe2013-02-27 14:31:02 -08001504 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001505 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506
1507 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001508 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001510 list_remove(&uc_info->list);
1511 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512
Eric Laurent994a6932013-07-17 11:51:42 -07001513 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 return ret;
1515}
1516
1517int start_input_stream(struct stream_in *in)
1518{
1519 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001520 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521 struct audio_usecase *uc_info;
1522 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301523 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524
Mingming Yin2664a5b2015-09-03 10:53:11 -07001525 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1526 if (get_usecase_from_list(adev, usecase) == NULL)
1527 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301528 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1529 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001530
Naresh Tanniru80659832014-06-04 18:17:56 +05301531
1532 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301533 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301534 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301535 goto error_config;
1536 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301537
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001538 /* Check if source matches incall recording usecase criteria */
1539 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1540 if (ret)
1541 goto error_config;
1542 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001543 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1544
1545 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1546 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1547 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001548 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001549 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001550
Eric Laurentb23d5282013-05-14 15:27:20 -07001551 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 if (in->pcm_device_id < 0) {
1553 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1554 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001555 ret = -EINVAL;
1556 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558
1559 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001561
1562 if (!uc_info) {
1563 ret = -ENOMEM;
1564 goto error_config;
1565 }
1566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 uc_info->id = in->usecase;
1568 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001569 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 uc_info->devices = in->device;
1571 uc_info->in_snd_device = SND_DEVICE_NONE;
1572 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001574 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301575 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1576 adev->perf_lock_opts,
1577 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301580 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1581 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001582
1583 unsigned int flags = PCM_IN;
1584 unsigned int pcm_open_retry_count = 0;
1585
1586 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1587 flags |= PCM_MMAP | PCM_NOIRQ;
1588 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001589 } else if (in->realtime) {
1590 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 }
1592
1593 while (1) {
1594 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1595 flags, &in->config);
1596 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1597 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1598 if (in->pcm != NULL) {
1599 pcm_close(in->pcm);
1600 in->pcm = NULL;
1601 }
1602 if (pcm_open_retry_count-- == 0) {
1603 ret = -EIO;
1604 goto error_open;
1605 }
1606 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1607 continue;
1608 }
1609 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001611
1612 ALOGV("%s: pcm_prepare", __func__);
1613 ret = pcm_prepare(in->pcm);
1614 if (ret < 0) {
1615 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1616 pcm_close(in->pcm);
1617 in->pcm = NULL;
1618 goto error_open;
1619 }
1620
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001621 register_in_stream(in);
1622 if (in->realtime) {
1623 ret = pcm_start(in->pcm);
1624 if (ret < 0)
1625 goto error_open;
1626 }
1627
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301628 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001629 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001630
Eric Laurentc8400632013-02-14 19:04:54 -08001631 return ret;
1632
1633error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301634 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001636error_config:
1637 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301638 /*
1639 * sleep 50ms to allow sufficient time for kernel
1640 * drivers to recover incases like SSR.
1641 */
1642 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001644
1645 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646}
1647
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001648void lock_input_stream(struct stream_in *in)
1649{
1650 pthread_mutex_lock(&in->pre_lock);
1651 pthread_mutex_lock(&in->lock);
1652 pthread_mutex_unlock(&in->pre_lock);
1653}
1654
1655void lock_output_stream(struct stream_out *out)
1656{
1657 pthread_mutex_lock(&out->pre_lock);
1658 pthread_mutex_lock(&out->lock);
1659 pthread_mutex_unlock(&out->pre_lock);
1660}
1661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662/* must be called with out->lock locked */
1663static int send_offload_cmd_l(struct stream_out* out, int command)
1664{
1665 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1666
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001667 if (!cmd) {
1668 ALOGE("failed to allocate mem for command 0x%x", command);
1669 return -ENOMEM;
1670 }
1671
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672 ALOGVV("%s %d", __func__, command);
1673
1674 cmd->cmd = command;
1675 list_add_tail(&out->offload_cmd_list, &cmd->node);
1676 pthread_cond_signal(&out->offload_cond);
1677 return 0;
1678}
1679
1680/* must be called iwth out->lock locked */
1681static void stop_compressed_output_l(struct stream_out *out)
1682{
1683 out->offload_state = OFFLOAD_STATE_IDLE;
1684 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001685 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001686 if (out->compr != NULL) {
1687 compress_stop(out->compr);
1688 while (out->offload_thread_blocked) {
1689 pthread_cond_wait(&out->cond, &out->lock);
1690 }
1691 }
1692}
1693
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001694bool is_offload_usecase(audio_usecase_t uc_id)
1695{
1696 unsigned int i;
1697 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1698 if (uc_id == offload_usecases[i])
1699 return true;
1700 }
1701 return false;
1702}
1703
vivek mehta446c3962015-09-14 10:57:35 -07001704static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001705{
vivek mehta446c3962015-09-14 10:57:35 -07001706 audio_usecase_t ret_uc = USECASE_INVALID;
1707 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001708 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001709 if (!adev->multi_offload_enable) {
1710 if (is_direct_pcm)
1711 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1712 else
1713 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001714
vivek mehta446c3962015-09-14 10:57:35 -07001715 pthread_mutex_lock(&adev->lock);
1716 if (get_usecase_from_list(adev, ret_uc) != NULL)
1717 ret_uc = USECASE_INVALID;
1718 pthread_mutex_unlock(&adev->lock);
1719
1720 return ret_uc;
1721 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001722
1723 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001724 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1725 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1726 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1727 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001728 break;
1729 }
1730 }
vivek mehta446c3962015-09-14 10:57:35 -07001731
1732 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1733 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001734}
1735
1736static void free_offload_usecase(struct audio_device *adev,
1737 audio_usecase_t uc_id)
1738{
vivek mehta446c3962015-09-14 10:57:35 -07001739 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001740 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001741
1742 if (!adev->multi_offload_enable)
1743 return;
1744
1745 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1746 if (offload_usecases[offload_uc_index] == uc_id) {
1747 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001748 break;
1749 }
1750 }
1751 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1752}
1753
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754static void *offload_thread_loop(void *context)
1755{
1756 struct stream_out *out = (struct stream_out *) context;
1757 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001758 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1761 set_sched_policy(0, SP_FOREGROUND);
1762 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1763
1764 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001765 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 for (;;) {
1767 struct offload_cmd *cmd = NULL;
1768 stream_callback_event_t event;
1769 bool send_callback = false;
1770
1771 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1772 __func__, list_empty(&out->offload_cmd_list),
1773 out->offload_state);
1774 if (list_empty(&out->offload_cmd_list)) {
1775 ALOGV("%s SLEEPING", __func__);
1776 pthread_cond_wait(&out->offload_cond, &out->lock);
1777 ALOGV("%s RUNNING", __func__);
1778 continue;
1779 }
1780
1781 item = list_head(&out->offload_cmd_list);
1782 cmd = node_to_item(item, struct offload_cmd, node);
1783 list_remove(item);
1784
1785 ALOGVV("%s STATE %d CMD %d out->compr %p",
1786 __func__, out->offload_state, cmd->cmd, out->compr);
1787
1788 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1789 free(cmd);
1790 break;
1791 }
1792
1793 if (out->compr == NULL) {
1794 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001795 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 pthread_cond_signal(&out->cond);
1797 continue;
1798 }
1799 out->offload_thread_blocked = true;
1800 pthread_mutex_unlock(&out->lock);
1801 send_callback = false;
1802 switch(cmd->cmd) {
1803 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001804 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001806 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 send_callback = true;
1808 event = STREAM_CBK_EVENT_WRITE_READY;
1809 break;
1810 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001811 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301812 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001813 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301814 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001815 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301816 if (ret < 0)
1817 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301818 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301819 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001820 compress_drain(out->compr);
1821 else
1822 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301823 if (ret != -ENETRESET) {
1824 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301825 pthread_mutex_lock(&out->lock);
1826 out->send_new_metadata = 1;
1827 out->send_next_track_params = true;
1828 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301829 event = STREAM_CBK_EVENT_DRAIN_READY;
1830 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1831 } else
1832 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001833 break;
1834 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001835 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001837 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001838 send_callback = true;
1839 event = STREAM_CBK_EVENT_DRAIN_READY;
1840 break;
1841 default:
1842 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1843 break;
1844 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001845 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001846 out->offload_thread_blocked = false;
1847 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001848 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001849 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001851 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001852 free(cmd);
1853 }
1854
1855 pthread_cond_signal(&out->cond);
1856 while (!list_empty(&out->offload_cmd_list)) {
1857 item = list_head(&out->offload_cmd_list);
1858 list_remove(item);
1859 free(node_to_item(item, struct offload_cmd, node));
1860 }
1861 pthread_mutex_unlock(&out->lock);
1862
1863 return NULL;
1864}
1865
1866static int create_offload_callback_thread(struct stream_out *out)
1867{
1868 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1869 list_init(&out->offload_cmd_list);
1870 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1871 offload_thread_loop, out);
1872 return 0;
1873}
1874
1875static int destroy_offload_callback_thread(struct stream_out *out)
1876{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001877 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 stop_compressed_output_l(out);
1879 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1880
1881 pthread_mutex_unlock(&out->lock);
1882 pthread_join(out->offload_thread, (void **) NULL);
1883 pthread_cond_destroy(&out->offload_cond);
1884
1885 return 0;
1886}
1887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888static int stop_output_stream(struct stream_out *out)
1889{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301890 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 struct audio_usecase *uc_info;
1892 struct audio_device *adev = out->dev;
1893
Eric Laurent994a6932013-07-17 11:51:42 -07001894 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 uc_info = get_usecase_from_list(adev, out->usecase);
1897 if (uc_info == NULL) {
1898 ALOGE("%s: Could not find the usecase (%d) in the list",
1899 __func__, out->usecase);
1900 return -EINVAL;
1901 }
1902
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001903 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301904 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001905 if (adev->visualizer_stop_output != NULL)
1906 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001907
1908 audio_extn_dts_remove_state_notifier_node(out->usecase);
1909
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001910 if (adev->offload_effects_stop_output != NULL)
1911 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1912 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001913
Eric Laurent150dbfe2013-02-27 14:31:02 -08001914 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001915 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916
1917 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001918 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001920 list_remove(&uc_info->list);
1921 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001923 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301924 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001925 ALOGV("Disable passthrough , reset mixer to pcm");
1926 /* NO_PASSTHROUGH */
1927 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001928 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001929 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1930 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001931
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301932 /* Must be called after removing the usecase from list */
1933 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301934 audio_extn_keep_alive_start();
1935
Eric Laurent994a6932013-07-17 11:51:42 -07001936 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 return ret;
1938}
1939
1940int start_output_stream(struct stream_out *out)
1941{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943 struct audio_usecase *uc_info;
1944 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301945 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001947 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1948 ret = -EINVAL;
1949 goto error_config;
1950 }
1951
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301952 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1953 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1954 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301955
Naresh Tanniru80659832014-06-04 18:17:56 +05301956 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301957 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301958 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301959 goto error_config;
1960 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301961
Eric Laurentb23d5282013-05-14 15:27:20 -07001962 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 if (out->pcm_device_id < 0) {
1964 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1965 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001966 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001967 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 }
1969
1970 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001971
1972 if (!uc_info) {
1973 ret = -ENOMEM;
1974 goto error_config;
1975 }
1976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 uc_info->id = out->usecase;
1978 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001979 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001980 uc_info->devices = out->devices;
1981 uc_info->in_snd_device = SND_DEVICE_NONE;
1982 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001983 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301985 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1986 adev->perf_lock_opts,
1987 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301988
1989 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1990 audio_extn_keep_alive_stop();
1991 if (audio_extn_passthru_is_enabled() &&
1992 audio_extn_passthru_is_passthrough_stream(out)) {
1993 audio_extn_passthru_on_start(out);
1994 audio_extn_passthru_update_stream_configuration(adev, out);
1995 }
1996 }
1997
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001998 select_devices(adev, out->usecase);
1999
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002000 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2001 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002002 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002003 unsigned int flags = PCM_OUT;
2004 unsigned int pcm_open_retry_count = 0;
2005 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2006 flags |= PCM_MMAP | PCM_NOIRQ;
2007 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002008 } else if (out->realtime) {
2009 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002010 } else
2011 flags |= PCM_MONOTONIC;
2012
2013 while (1) {
2014 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2015 flags, &out->config);
2016 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2017 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2018 if (out->pcm != NULL) {
2019 pcm_close(out->pcm);
2020 out->pcm = NULL;
2021 }
2022 if (pcm_open_retry_count-- == 0) {
2023 ret = -EIO;
2024 goto error_open;
2025 }
2026 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2027 continue;
2028 }
2029 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002031
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2033 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002034
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002035 ALOGV("%s: pcm_prepare", __func__);
2036 if (pcm_is_ready(out->pcm)) {
2037 ret = pcm_prepare(out->pcm);
2038 if (ret < 0) {
2039 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2040 pcm_close(out->pcm);
2041 out->pcm = NULL;
2042 goto error_open;
2043 }
2044 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002045 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002046 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2047 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002049 out->compr = compress_open(adev->snd_card,
2050 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 COMPRESS_IN, &out->compr_config);
2052 if (out->compr && !is_compress_ready(out->compr)) {
2053 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2054 compress_close(out->compr);
2055 out->compr = NULL;
2056 ret = -EIO;
2057 goto error_open;
2058 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302059 /* compress_open sends params of the track, so reset the flag here */
2060 out->is_compr_metadata_avail = false;
2061
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 if (out->offload_callback)
2063 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002064
Fred Oh3f43e742015-03-04 18:42:34 -08002065 /* Since small bufs uses blocking writes, a write will be blocked
2066 for the default max poll time (20s) in the event of an SSR.
2067 Reduce the poll time to observe and deal with SSR faster.
2068 */
Ashish Jain5106d362016-05-11 19:23:33 +05302069 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002070 compress_set_max_poll_wait(out->compr, 1000);
2071 }
2072
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002073 audio_extn_dts_create_state_notifier_node(out->usecase);
2074 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2075 popcount(out->channel_mask),
2076 out->playback_started);
2077
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002078#ifdef DS1_DOLBY_DDP_ENABLED
2079 if (audio_extn_is_dolby_format(out->format))
2080 audio_extn_dolby_send_ddp_endp_params(adev);
2081#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302082 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002083 if (adev->visualizer_start_output != NULL)
2084 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2085 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302086 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002087 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002088 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002090
2091 if (ret == 0) {
2092 register_out_stream(out);
2093 if (out->realtime) {
2094 ret = pcm_start(out->pcm);
2095 if (ret < 0)
2096 goto error_open;
2097 }
2098 }
2099
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302100 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002101 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002102
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002103 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302105 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002107error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302108 /*
2109 * sleep 50ms to allow sufficient time for kernel
2110 * drivers to recover incases like SSR.
2111 */
2112 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002113 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114}
2115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116static int check_input_parameters(uint32_t sample_rate,
2117 audio_format_t format,
2118 int channel_count)
2119{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002120 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302122 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2123 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2124 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002125 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302126 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002127
2128 switch (channel_count) {
2129 case 1:
2130 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302131 case 3:
2132 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002133 case 6:
2134 break;
2135 default:
2136 ret = -EINVAL;
2137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138
2139 switch (sample_rate) {
2140 case 8000:
2141 case 11025:
2142 case 12000:
2143 case 16000:
2144 case 22050:
2145 case 24000:
2146 case 32000:
2147 case 44100:
2148 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302149 case 96000:
2150 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 break;
2152 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002153 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 }
2155
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002156 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157}
2158
2159static size_t get_input_buffer_size(uint32_t sample_rate,
2160 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002161 int channel_count,
2162 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163{
2164 size_t size = 0;
2165
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002166 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2167 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002169 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002170 if (is_low_latency)
2171 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302172
2173 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002175 /* make sure the size is multiple of 32 bytes
2176 * At 48 kHz mono 16-bit PCM:
2177 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2178 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2179 */
2180 size += 0x1f;
2181 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002182
2183 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184}
2185
Ashish Jain5106d362016-05-11 19:23:33 +05302186static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2187{
2188 uint64_t actual_frames_rendered = 0;
2189 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2190
2191 /* This adjustment accounts for buffering after app processor.
2192 * It is based on estimated DSP latency per use case, rather than exact.
2193 */
2194 int64_t platform_latency = platform_render_latency(out->usecase) *
2195 out->sample_rate / 1000000LL;
2196
2197 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2198 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2199 * hence only estimate.
2200 */
2201 int64_t signed_frames = out->written - kernel_buffer_size;
2202
2203 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2204
2205 if (signed_frames > 0)
2206 actual_frames_rendered = signed_frames;
2207
2208 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2209 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2210 (long long int)out->written, (int)kernel_buffer_size,
2211 audio_bytes_per_sample(out->compr_config.codec->format),
2212 popcount(out->channel_mask));
2213
2214 return actual_frames_rendered;
2215}
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2218{
2219 struct stream_out *out = (struct stream_out *)stream;
2220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222}
2223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002224static int out_set_sample_rate(struct audio_stream *stream __unused,
2225 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226{
2227 return -ENOSYS;
2228}
2229
2230static size_t out_get_buffer_size(const struct audio_stream *stream)
2231{
2232 struct stream_out *out = (struct stream_out *)stream;
2233
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002234 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002236 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2237 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302238 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302239 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002241 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002242 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243}
2244
2245static uint32_t out_get_channels(const struct audio_stream *stream)
2246{
2247 struct stream_out *out = (struct stream_out *)stream;
2248
2249 return out->channel_mask;
2250}
2251
2252static audio_format_t out_get_format(const struct audio_stream *stream)
2253{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 struct stream_out *out = (struct stream_out *)stream;
2255
2256 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257}
2258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002259static int out_set_format(struct audio_stream *stream __unused,
2260 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261{
2262 return -ENOSYS;
2263}
2264
2265static int out_standby(struct audio_stream *stream)
2266{
2267 struct stream_out *out = (struct stream_out *)stream;
2268 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302270 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2271 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002273 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002275 if (adev->adm_deregister_stream)
2276 adev->adm_deregister_stream(adev->adm_data, out->handle);
2277
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002278 if (is_offload_usecase(out->usecase))
2279 stop_compressed_output_l(out);
2280
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002281 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002283 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2284 voice_extn_compress_voip_close_output_stream(stream);
2285 pthread_mutex_unlock(&adev->lock);
2286 pthread_mutex_unlock(&out->lock);
2287 ALOGD("VOIP output entered standby");
2288 return 0;
2289 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002290 if (out->pcm) {
2291 pcm_close(out->pcm);
2292 out->pcm = NULL;
2293 }
2294 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002295 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302296 out->send_next_track_params = false;
2297 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002298 out->gapless_mdata.encoder_delay = 0;
2299 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 if (out->compr != NULL) {
2301 compress_close(out->compr);
2302 out->compr = NULL;
2303 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002304 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002306 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 }
2308 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302309 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 return 0;
2311}
2312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002313static int out_dump(const struct audio_stream *stream __unused,
2314 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315{
2316 return 0;
2317}
2318
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002319static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2320{
2321 int ret = 0;
2322 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002323
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002324 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002325 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002326 return -EINVAL;
2327 }
2328
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302329 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002330
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002331 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2332 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302333 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002334 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002335 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2336 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302337 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002338 }
2339
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002340 ALOGV("%s new encoder delay %u and padding %u", __func__,
2341 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2342
2343 return 0;
2344}
2345
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002346static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2347{
2348 return out == adev->primary_output || out == adev->voice_tx_output;
2349}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354 struct audio_device *adev = out->dev;
2355 struct str_parms *parms;
2356 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002357 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358
sangwoobc677242013-08-08 16:53:43 +09002359 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002360 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302362 if (!parms)
2363 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002364 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2365 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002367 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002368 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002370 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002371 * When HDMI cable is unplugged the music playback is paused and
2372 * the policy manager sends routing=0. But the audioflinger continues
2373 * to write data until standby time (3sec). As the HDMI core is
2374 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002375 * Avoid this by routing audio to speaker until standby.
2376 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002377 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2378 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302379 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002380 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2381 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002382 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302383 /*
2384 * When A2DP is disconnected the
2385 * music playback is paused and the policy manager sends routing=0
2386 * But the audioflingercontinues to write data until standby time
2387 * (3sec). As BT is turned off, the write gets blocked.
2388 * Avoid this by routing audio to speaker until standby.
2389 */
2390 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2391 (val == AUDIO_DEVICE_NONE)) {
2392 val = AUDIO_DEVICE_OUT_SPEAKER;
2393 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394
2395 /*
2396 * select_devices() call below switches all the usecases on the same
2397 * backend to the new device. Refer to check_usecases_codec_backend() in
2398 * the select_devices(). But how do we undo this?
2399 *
2400 * For example, music playback is active on headset (deep-buffer usecase)
2401 * and if we go to ringtones and select a ringtone, low-latency usecase
2402 * will be started on headset+speaker. As we can't enable headset+speaker
2403 * and headset devices at the same time, select_devices() switches the music
2404 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2405 * So when the ringtone playback is completed, how do we undo the same?
2406 *
2407 * We are relying on the out_set_parameters() call on deep-buffer output,
2408 * once the ringtone playback is ended.
2409 * NOTE: We should not check if the current devices are same as new devices.
2410 * Because select_devices() must be called to switch back the music
2411 * playback to headset.
2412 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002413 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002414 audio_devices_t new_dev = val;
2415 bool same_dev = out->devices == new_dev;
2416 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002417
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002418 if (output_drives_call(adev, out)) {
2419 if(!voice_is_in_call(adev)) {
2420 if (adev->mode == AUDIO_MODE_IN_CALL) {
2421 adev->current_call_output = out;
2422 ret = voice_start_call(adev);
2423 }
2424 } else {
2425 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002426 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002427 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002428 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002429
2430 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002431 if (!same_dev) {
2432 ALOGV("update routing change");
2433 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302434 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2435 adev->perf_lock_opts,
2436 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002437 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002438 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302439 if (!same_dev)
2440 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002441 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002442 }
2443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002445 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002447
2448 if (out == adev->primary_output) {
2449 pthread_mutex_lock(&adev->lock);
2450 audio_extn_set_parameters(adev, parms);
2451 pthread_mutex_unlock(&adev->lock);
2452 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002453 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002454 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002455 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002456
2457 audio_extn_dts_create_state_notifier_node(out->usecase);
2458 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2459 popcount(out->channel_mask),
2460 out->playback_started);
2461
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002462 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002463 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302466error:
Eric Laurent994a6932013-07-17 11:51:42 -07002467 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 return ret;
2469}
2470
2471static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2472{
2473 struct stream_out *out = (struct stream_out *)stream;
2474 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002475 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 char value[256];
2477 struct str_parms *reply = str_parms_create();
2478 size_t i, j;
2479 int ret;
2480 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002481
2482 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002483 if (reply) {
2484 str_parms_destroy(reply);
2485 }
2486 if (query) {
2487 str_parms_destroy(query);
2488 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002489 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2490 return NULL;
2491 }
2492
Eric Laurent994a6932013-07-17 11:51:42 -07002493 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2495 if (ret >= 0) {
2496 value[0] = '\0';
2497 i = 0;
2498 while (out->supported_channel_masks[i] != 0) {
2499 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2500 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2501 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002502 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002504 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 first = false;
2506 break;
2507 }
2508 }
2509 i++;
2510 }
2511 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2512 str = str_parms_to_str(reply);
2513 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002514 voice_extn_out_get_parameters(out, query, reply);
2515 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002516 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002517 free(str);
2518 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002521
Alexy Joseph62142aa2015-11-16 15:10:34 -08002522
2523 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2524 if (ret >= 0) {
2525 value[0] = '\0';
2526 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2527 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302528 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002529 } else {
2530 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302531 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002532 }
2533 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002534 if (str)
2535 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002536 str = str_parms_to_str(reply);
2537 }
2538
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002539 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2540 if (ret >= 0) {
2541 value[0] = '\0';
2542 i = 0;
2543 first = true;
2544 while (out->supported_formats[i] != 0) {
2545 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2546 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2547 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002548 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002549 }
2550 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2551 first = false;
2552 break;
2553 }
2554 }
2555 i++;
2556 }
2557 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002558 if (str)
2559 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002560 str = str_parms_to_str(reply);
2561 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002562
2563 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2564 if (ret >= 0) {
2565 value[0] = '\0';
2566 i = 0;
2567 first = true;
2568 while (out->supported_sample_rates[i] != 0) {
2569 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2570 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2571 if (!first) {
2572 strlcat(value, "|", sizeof(value));
2573 }
2574 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2575 first = false;
2576 break;
2577 }
2578 }
2579 i++;
2580 }
2581 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2582 if (str)
2583 free(str);
2584 str = str_parms_to_str(reply);
2585 }
2586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 str_parms_destroy(query);
2588 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002589 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 return str;
2591}
2592
2593static uint32_t out_get_latency(const struct audio_stream_out *stream)
2594{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002595 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002597 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
Alexy Josephaa54c872014-12-03 02:46:47 -08002599 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002600 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002601 } else if (out->realtime) {
2602 // since the buffer won't be filled up faster than realtime,
2603 // return a smaller number
2604 if (out->config.rate)
2605 period_ms = (out->af_period_multiplier * out->config.period_size *
2606 1000) / (out->config.rate);
2607 else
2608 period_ms = 0;
2609 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002610 } else {
2611 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002613 }
2614
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302615 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002616 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617}
2618
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302619static float AmpToDb(float amplification)
2620{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302621 float db = DSD_VOLUME_MIN_DB;
2622 if (amplification > 0) {
2623 db = 20 * log10(amplification);
2624 if(db < DSD_VOLUME_MIN_DB)
2625 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302626 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302627 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302628}
2629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630static int out_set_volume(struct audio_stream_out *stream, float left,
2631 float right)
2632{
Eric Laurenta9024de2013-04-04 09:19:12 -07002633 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 int volume[2];
2635
Eric Laurenta9024de2013-04-04 09:19:12 -07002636 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2637 /* only take left channel into account: the API is for stereo anyway */
2638 out->muted = (left == 0.0f);
2639 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002640 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302641 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002642 /*
2643 * Set mute or umute on HDMI passthrough stream.
2644 * Only take left channel into account.
2645 * Mute is 0 and unmute 1
2646 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302647 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302648 } else if (out->format == AUDIO_FORMAT_DSD){
2649 char mixer_ctl_name[128] = "DSD Volume";
2650 struct audio_device *adev = out->dev;
2651 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2652
2653 if (!ctl) {
2654 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2655 __func__, mixer_ctl_name);
2656 return -EINVAL;
2657 }
2658 volume[0] = (int)(AmpToDb(left));
2659 volume[1] = (int)(AmpToDb(right));
2660 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2661 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002662 } else {
2663 char mixer_ctl_name[128];
2664 struct audio_device *adev = out->dev;
2665 struct mixer_ctl *ctl;
2666 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002667 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002669 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2670 "Compress Playback %d Volume", pcm_device_id);
2671 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2672 if (!ctl) {
2673 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2674 __func__, mixer_ctl_name);
2675 return -EINVAL;
2676 }
2677 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2678 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2679 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2680 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002681 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002682 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 return -ENOSYS;
2685}
2686
2687static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2688 size_t bytes)
2689{
2690 struct stream_out *out = (struct stream_out *)stream;
2691 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302692 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002693 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002695 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302696
Naresh Tanniru80659832014-06-04 18:17:56 +05302697 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002698
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302699 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302700 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302701 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2702 pthread_mutex_unlock(&out->lock);
2703 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302704 } else {
2705 /* increase written size during SSR to avoid mismatch
2706 * with the written frames count in AF
2707 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002708 // bytes per frame
2709 size_t bpf = audio_bytes_per_sample(out->format) *
2710 audio_channel_count_from_out_mask(out->channel_mask);
2711 if (bpf != 0)
2712 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302713 ALOGD(" %s: sound card is not active/SSR state", __func__);
2714 ret= -EIO;
2715 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302716 }
2717 }
2718
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302719 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302720 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2721 if (audio_bytes_per_sample(out->format) != 0)
2722 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2723 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302724 goto exit;
2725 }
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002728 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002729 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002730 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2731 ret = voice_extn_compress_voip_start_output_stream(out);
2732 else
2733 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002734 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002735 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002737 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 goto exit;
2739 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002740
2741 if (last_known_cal_step != -1) {
2742 ALOGD("%s: retry previous failed cal level set", __func__);
2743 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746
Ashish Jain81eb2a82015-05-13 10:52:34 +05302747 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002748 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302749 adev->is_channel_status_set = true;
2750 }
2751
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002752 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002753 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002754 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002755 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002756 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2757 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302758 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2759 ALOGD("copl(%p):send next track params in gapless", out);
2760 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2761 out->send_next_track_params = false;
2762 out->is_compr_metadata_avail = false;
2763 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002764 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302765 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302766 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002767
Ashish Jain83a6cc22016-06-28 14:34:17 +05302768 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302769 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302770 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302771 pthread_mutex_unlock(&out->lock);
2772 return -EINVAL;
2773 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302774 audio_format_t dst_format = out->hal_op_format;
2775 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302776
2777 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2778 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2779
Ashish Jain83a6cc22016-06-28 14:34:17 +05302780 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302781 dst_format,
2782 buffer,
2783 src_format,
2784 frames);
2785
Ashish Jain83a6cc22016-06-28 14:34:17 +05302786 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302787 bytes_to_write);
2788
2789 /*Convert written bytes in audio flinger format*/
2790 if (ret > 0)
2791 ret = ((ret * format_to_bitwidth_table[out->format]) /
2792 format_to_bitwidth_table[dst_format]);
2793 }
2794 } else
2795 ret = compress_write(out->compr, buffer, bytes);
2796
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302797 if (ret < 0)
2798 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302799 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302800 /*msg to cb thread only if non blocking write is enabled*/
2801 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302802 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302804 } else if (-ENETRESET == ret) {
2805 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2806 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2807 pthread_mutex_unlock(&out->lock);
2808 out_standby(&out->stream.common);
2809 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810 }
Ashish Jain5106d362016-05-11 19:23:33 +05302811 if ( ret == (ssize_t)bytes && !out->non_blocking)
2812 out->written += bytes;
2813
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302814 /* Call compr start only when non-zero bytes of data is there to be rendered */
2815 if (!out->playback_started && ret > 0) {
2816 int status = compress_start(out->compr);
2817 if (status < 0) {
2818 ret = status;
2819 ALOGE("%s: compr start failed with err %d", __func__, errno);
2820 goto exit;
2821 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002822 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 out->playback_started = 1;
2824 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002825
2826 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2827 popcount(out->channel_mask),
2828 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 }
2830 pthread_mutex_unlock(&out->lock);
2831 return ret;
2832 } else {
2833 if (out->pcm) {
2834 if (out->muted)
2835 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002836
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302837 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002838
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002839 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002840
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002841 if (out->config.rate)
2842 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2843 out->config.rate;
2844
2845 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2846
2847 request_out_focus(out, ns);
2848
2849 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002850 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002851 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302852 out->convert_buffer != NULL) {
2853
2854 memcpy_by_audio_format(out->convert_buffer,
2855 out->hal_op_format,
2856 buffer,
2857 out->hal_ip_format,
2858 out->config.period_size * out->config.channels);
2859
2860 ret = pcm_write(out->pcm, out->convert_buffer,
2861 (out->config.period_size *
2862 out->config.channels *
2863 format_to_bitwidth_table[out->hal_op_format]));
2864 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002865 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302866 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002867
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002868 release_out_focus(out);
2869
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302870 if (ret < 0)
2871 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302872 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2873 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2874 else
2875 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 }
2878
2879exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302880 /* ToDo: There may be a corner case when SSR happens back to back during
2881 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302882 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302883 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302884 }
2885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 pthread_mutex_unlock(&out->lock);
2887
2888 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002889 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002890 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302891 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302892 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302893 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302894 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302895 out->standby = true;
2896 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302898 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2899 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2900 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 }
2902 return bytes;
2903}
2904
2905static int out_get_render_position(const struct audio_stream_out *stream,
2906 uint32_t *dsp_frames)
2907{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302909 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002910
2911 if (dsp_frames == NULL)
2912 return -EINVAL;
2913
2914 *dsp_frames = 0;
2915 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002916 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302917
2918 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2919 * this operation and adev_close_output_stream(where out gets reset).
2920 */
2921 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2922 *dsp_frames = get_actual_pcm_frames_rendered(out);
2923 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2924 return 0;
2925 }
2926
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002927 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302928 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302929 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302931 if (ret < 0)
2932 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302934 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 }
2936 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302937 if (-ENETRESET == ret) {
2938 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2939 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2940 return -EINVAL;
2941 } else if(ret < 0) {
2942 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2943 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302944 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2945 /*
2946 * Handle corner case where compress session is closed during SSR
2947 * and timestamp is queried
2948 */
2949 ALOGE(" ERROR: sound card not active, return error");
2950 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302951 } else {
2952 return 0;
2953 }
Zhou Song32a556e2015-05-05 10:46:56 +08002954 } else if (audio_is_linear_pcm(out->format)) {
2955 *dsp_frames = out->written;
2956 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 } else
2958 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959}
2960
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002961static int out_add_audio_effect(const struct audio_stream *stream __unused,
2962 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963{
2964 return 0;
2965}
2966
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002967static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2968 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969{
2970 return 0;
2971}
2972
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002973static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2974 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975{
2976 return -EINVAL;
2977}
2978
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002979static int out_get_presentation_position(const struct audio_stream_out *stream,
2980 uint64_t *frames, struct timespec *timestamp)
2981{
2982 struct stream_out *out = (struct stream_out *)stream;
2983 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002984 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002985
Ashish Jain5106d362016-05-11 19:23:33 +05302986 /* below piece of code is not guarded against any lock because audioFliner serializes
2987 * this operation and adev_close_output_stream( where out gets reset).
2988 */
2989 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2990 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2991 *frames = get_actual_pcm_frames_rendered(out);
2992 /* this is the best we can do */
2993 clock_gettime(CLOCK_MONOTONIC, timestamp);
2994 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2995 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2996 return 0;
2997 }
2998
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002999 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003000
Ashish Jain5106d362016-05-11 19:23:33 +05303001 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3002 ret = compress_get_tstamp(out->compr, &dsp_frames,
3003 &out->sample_rate);
3004 ALOGVV("%s rendered frames %ld sample_rate %d",
3005 __func__, dsp_frames, out->sample_rate);
3006 *frames = dsp_frames;
3007 if (ret < 0)
3008 ret = -errno;
3009 if (-ENETRESET == ret) {
3010 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3011 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3012 ret = -EINVAL;
3013 } else
3014 ret = 0;
3015 /* this is the best we can do */
3016 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003017 } else {
3018 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003019 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003020 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3021 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003022 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003023 // This adjustment accounts for buffering after app processor.
3024 // It is based on estimated DSP latency per use case, rather than exact.
3025 signed_frames -=
3026 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3027
Eric Laurent949a0892013-09-20 09:20:13 -07003028 // It would be unusual for this value to be negative, but check just in case ...
3029 if (signed_frames >= 0) {
3030 *frames = signed_frames;
3031 ret = 0;
3032 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003033 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303034 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3035 *frames = out->written;
3036 clock_gettime(CLOCK_MONOTONIC, timestamp);
3037 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003038 }
3039 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003040 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003041 return ret;
3042}
3043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044static int out_set_callback(struct audio_stream_out *stream,
3045 stream_callback_t callback, void *cookie)
3046{
3047 struct stream_out *out = (struct stream_out *)stream;
3048
3049 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003050 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 out->offload_callback = callback;
3052 out->offload_cookie = cookie;
3053 pthread_mutex_unlock(&out->lock);
3054 return 0;
3055}
3056
3057static int out_pause(struct audio_stream_out* stream)
3058{
3059 struct stream_out *out = (struct stream_out *)stream;
3060 int status = -ENOSYS;
3061 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003062 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003063 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003064 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303066 struct audio_device *adev = out->dev;
3067 int snd_scard_state = get_snd_card_state(adev);
3068
3069 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3070 status = compress_pause(out->compr);
3071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003073
Mingming Yin21854652016-04-13 11:54:02 -07003074 if (audio_extn_passthru_is_active()) {
3075 ALOGV("offload use case, pause passthru");
3076 audio_extn_passthru_on_pause(out);
3077 }
3078
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303079 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003080 audio_extn_dts_notify_playback_state(out->usecase, 0,
3081 out->sample_rate, popcount(out->channel_mask),
3082 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 }
3084 pthread_mutex_unlock(&out->lock);
3085 }
3086 return status;
3087}
3088
3089static int out_resume(struct audio_stream_out* stream)
3090{
3091 struct stream_out *out = (struct stream_out *)stream;
3092 int status = -ENOSYS;
3093 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003094 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003095 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003097 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303099 struct audio_device *adev = out->dev;
3100 int snd_scard_state = get_snd_card_state(adev);
3101
Mingming Yin21854652016-04-13 11:54:02 -07003102 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3103 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3104 pthread_mutex_lock(&out->dev->lock);
3105 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003106 pthread_mutex_unlock(&out->dev->lock);
3107 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303108 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003109 }
3110 if (!status) {
3111 out->offload_state = OFFLOAD_STATE_PLAYING;
3112 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303113 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003114 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3115 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 }
3117 pthread_mutex_unlock(&out->lock);
3118 }
3119 return status;
3120}
3121
3122static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3123{
3124 struct stream_out *out = (struct stream_out *)stream;
3125 int status = -ENOSYS;
3126 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003127 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003128 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3130 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3131 else
3132 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3133 pthread_mutex_unlock(&out->lock);
3134 }
3135 return status;
3136}
3137
3138static int out_flush(struct audio_stream_out* stream)
3139{
3140 struct stream_out *out = (struct stream_out *)stream;
3141 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003142 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003143 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003144 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003145 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3146 stop_compressed_output_l(out);
3147 out->written = 0;
3148 } else {
3149 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3150 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003152 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 return 0;
3154 }
3155 return -ENOSYS;
3156}
3157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158/** audio_stream_in implementation **/
3159static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3160{
3161 struct stream_in *in = (struct stream_in *)stream;
3162
3163 return in->config.rate;
3164}
3165
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003166static int in_set_sample_rate(struct audio_stream *stream __unused,
3167 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168{
3169 return -ENOSYS;
3170}
3171
3172static size_t in_get_buffer_size(const struct audio_stream *stream)
3173{
3174 struct stream_in *in = (struct stream_in *)stream;
3175
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003176 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3177 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003178 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3179 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003180
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003181 return in->config.period_size * in->af_period_multiplier *
3182 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183}
3184
3185static uint32_t in_get_channels(const struct audio_stream *stream)
3186{
3187 struct stream_in *in = (struct stream_in *)stream;
3188
3189 return in->channel_mask;
3190}
3191
3192static audio_format_t in_get_format(const struct audio_stream *stream)
3193{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003194 struct stream_in *in = (struct stream_in *)stream;
3195
3196 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197}
3198
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003199static int in_set_format(struct audio_stream *stream __unused,
3200 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201{
3202 return -ENOSYS;
3203}
3204
3205static int in_standby(struct audio_stream *stream)
3206{
3207 struct stream_in *in = (struct stream_in *)stream;
3208 struct audio_device *adev = in->dev;
3209 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303210 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3211 stream, in->usecase, use_case_table[in->usecase]);
3212
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003213 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003214 if (!in->standby && in->is_st_session) {
3215 ALOGD("%s: sound trigger pcm stop lab", __func__);
3216 audio_extn_sound_trigger_stop_lab(in);
3217 in->standby = 1;
3218 }
3219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003221 if (adev->adm_deregister_stream)
3222 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3223
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003224 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003226 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3227 voice_extn_compress_voip_close_input_stream(stream);
3228 ALOGD("VOIP input entered standby");
3229 } else {
3230 if (in->pcm) {
3231 pcm_close(in->pcm);
3232 in->pcm = NULL;
3233 }
3234 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003235 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003236 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 }
3238 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003239 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 return status;
3241}
3242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003243static int in_dump(const struct audio_stream *stream __unused,
3244 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245{
3246 return 0;
3247}
3248
3249static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3250{
3251 struct stream_in *in = (struct stream_in *)stream;
3252 struct audio_device *adev = in->dev;
3253 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003255 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303257 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 parms = str_parms_create_str(kvpairs);
3259
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303260 if (!parms)
3261 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003262 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003263 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003264
3265 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3266 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 val = atoi(value);
3268 /* no audio source uses val == 0 */
3269 if ((in->source != val) && (val != 0)) {
3270 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003271 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3272 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3273 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003274 (in->config.rate == 8000 || in->config.rate == 16000 ||
3275 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003276 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003277 err = voice_extn_compress_voip_open_input_stream(in);
3278 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003279 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003280 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003281 }
3282 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 }
3284 }
3285
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003286 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3287 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003289 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 in->device = val;
3291 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003292 if (!in->standby && !in->is_st_session) {
3293 ALOGV("update input routing change");
3294 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003295 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 }
3298 }
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003301 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302
3303 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303304error:
Eric Laurent994a6932013-07-17 11:51:42 -07003305 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 return ret;
3307}
3308
3309static char* in_get_parameters(const struct audio_stream *stream,
3310 const char *keys)
3311{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003312 struct stream_in *in = (struct stream_in *)stream;
3313 struct str_parms *query = str_parms_create_str(keys);
3314 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003315 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003316
3317 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003318 if (reply) {
3319 str_parms_destroy(reply);
3320 }
3321 if (query) {
3322 str_parms_destroy(query);
3323 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003324 ALOGE("in_get_parameters: failed to create query or reply");
3325 return NULL;
3326 }
3327
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003328 ALOGV("%s: enter: keys - %s", __func__, keys);
3329
3330 voice_extn_in_get_parameters(in, query, reply);
3331
3332 str = str_parms_to_str(reply);
3333 str_parms_destroy(query);
3334 str_parms_destroy(reply);
3335
3336 ALOGV("%s: exit: returns - %s", __func__, str);
3337 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338}
3339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340static int in_set_gain(struct audio_stream_in *stream __unused,
3341 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342{
3343 return 0;
3344}
3345
3346static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3347 size_t bytes)
3348{
3349 struct stream_in *in = (struct stream_in *)stream;
3350 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303351 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303352 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303353 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003355 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303356
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003357 if (in->is_st_session) {
3358 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3359 /* Read from sound trigger HAL */
3360 audio_extn_sound_trigger_read(in, buffer, bytes);
3361 pthread_mutex_unlock(&in->lock);
3362 return bytes;
3363 }
3364
Ashish Jainbbce4322016-02-16 13:25:27 +05303365 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003366 ALOGD(" %s: sound card is not active/SSR state", __func__);
3367 ret= -EIO;;
3368 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303369 }
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003372 pthread_mutex_lock(&adev->lock);
3373 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3374 ret = voice_extn_compress_voip_start_input_stream(in);
3375 else
3376 ret = start_input_stream(in);
3377 pthread_mutex_unlock(&adev->lock);
3378 if (ret != 0) {
3379 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 }
3381 in->standby = 0;
3382 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003384 // what's the duration requested by the client?
3385 long ns = 0;
3386
3387 if (in->config.rate)
3388 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3389 in->config.rate;
3390
3391 request_in_focus(in, ns);
3392 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303395 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003396 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303397 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003398 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003399 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003400 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303401 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003402 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303403 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3404 if (bytes % 4 == 0) {
3405 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3406 int_buf_stream = buffer;
3407 for (size_t itt=0; itt < bytes/4 ; itt++) {
3408 int_buf_stream[itt] >>= 8;
3409 }
3410 } else {
3411 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415 } if (ret < 0) {
3416 ret = -errno;
3417 }
3418 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 }
3420
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003421 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 /*
3424 * Instead of writing zeroes here, we could trust the hardware
3425 * to always provide zeroes when muted.
3426 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303427 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3428 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 memset(buffer, 0, bytes);
3430
3431exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303432 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303433 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003434 if (-ENETRESET == ret)
3435 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 pthread_mutex_unlock(&in->lock);
3438
3439 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303440 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303441 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303442 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303443 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303444 in->standby = true;
3445 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303446 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003448 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303449 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303450 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 }
3452 return bytes;
3453}
3454
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003455static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456{
3457 return 0;
3458}
3459
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003460static int add_remove_audio_effect(const struct audio_stream *stream,
3461 effect_handle_t effect,
3462 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003464 struct stream_in *in = (struct stream_in *)stream;
3465 int status = 0;
3466 effect_descriptor_t desc;
3467
3468 status = (*effect)->get_descriptor(effect, &desc);
3469 if (status != 0)
3470 return status;
3471
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003472 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003473 pthread_mutex_lock(&in->dev->lock);
3474 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3475 in->enable_aec != enable &&
3476 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3477 in->enable_aec = enable;
3478 if (!in->standby)
3479 select_devices(in->dev, in->usecase);
3480 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003481 if (in->enable_ns != enable &&
3482 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3483 in->enable_ns = enable;
3484 if (!in->standby)
3485 select_devices(in->dev, in->usecase);
3486 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003487 pthread_mutex_unlock(&in->dev->lock);
3488 pthread_mutex_unlock(&in->lock);
3489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 return 0;
3491}
3492
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493static int in_add_audio_effect(const struct audio_stream *stream,
3494 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
Eric Laurent994a6932013-07-17 11:51:42 -07003496 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003497 return add_remove_audio_effect(stream, effect, true);
3498}
3499
3500static int in_remove_audio_effect(const struct audio_stream *stream,
3501 effect_handle_t effect)
3502{
Eric Laurent994a6932013-07-17 11:51:42 -07003503 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003504 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505}
3506
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303507int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 audio_io_handle_t handle,
3509 audio_devices_t devices,
3510 audio_output_flags_t flags,
3511 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003512 struct audio_stream_out **stream_out,
3513 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514{
3515 struct audio_device *adev = (struct audio_device *)dev;
3516 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303517 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003518 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303521
3522 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3523 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003524 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303525 return -EINVAL;
3526 }
3527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3529
Mingming Yin3a941d42016-02-17 18:08:05 -08003530 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3531 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303532 devices, flags, &out->stream);
3533
3534
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003535 if (!out) {
3536 return -ENOMEM;
3537 }
3538
Haynes Mathew George204045b2015-02-25 20:32:03 -08003539 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003540 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003541 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543 if (devices == AUDIO_DEVICE_NONE)
3544 devices = AUDIO_DEVICE_OUT_SPEAKER;
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 out->flags = flags;
3547 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003548 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003549 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 out->sample_rate = config->sample_rate;
3551 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3552 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003553 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003554 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003555 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303556 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
Mingming Yin3a941d42016-02-17 18:08:05 -08003558 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3559 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3560 pthread_mutex_lock(&adev->lock);
3561 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3562 ret = read_hdmi_sink_caps(out);
3563 pthread_mutex_unlock(&adev->lock);
3564 if (ret != 0) {
3565 if (ret == -ENOSYS) {
3566 /* ignore and go with default */
3567 ret = 0;
3568 } else {
3569 ALOGE("error reading hdmi sink caps");
3570 goto error_open;
3571 }
3572 }
3573 }
3574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003576 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303577 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3578 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003579 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3580 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3581
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003582 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003583 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3584 /*
3585 * Do not handle stereo output in Multi-channel cases
3586 * Stereo case is handled in normal playback path
3587 */
3588 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3589 ret = AUDIO_CHANNEL_OUT_STEREO;
3590 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003591
3592 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3593 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003594 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003595 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003596 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003597
3598 if (config->sample_rate == 0)
3599 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3600 if (config->channel_mask == 0)
3601 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003602 if (config->format == 0)
3603 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003604
3605 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003607 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3609 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003611 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003613 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3614 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003615 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003616 ret = voice_extn_compress_voip_open_output_stream(out);
3617 if (ret != 0) {
3618 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3619 __func__, ret);
3620 goto error_open;
3621 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003622 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3623 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3624
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003625 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3626 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3627 ALOGE("%s: Unsupported Offload information", __func__);
3628 ret = -EINVAL;
3629 goto error_open;
3630 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003631
Mingming Yin3a941d42016-02-17 18:08:05 -08003632 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003633 if(config->offload_info.format == 0)
3634 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003635 if (config->offload_info.sample_rate == 0)
3636 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003637 }
3638
Mingming Yin90310102013-11-13 16:57:00 -08003639 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303640 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003641 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003642 ret = -EINVAL;
3643 goto error_open;
3644 }
3645
3646 out->compr_config.codec = (struct snd_codec *)
3647 calloc(1, sizeof(struct snd_codec));
3648
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003649 if (!out->compr_config.codec) {
3650 ret = -ENOMEM;
3651 goto error_open;
3652 }
3653
vivek mehta0ea887a2015-08-26 14:01:20 -07003654 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303655 out->stream.pause = out_pause;
3656 out->stream.flush = out_flush;
3657 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003658 out->usecase = get_offload_usecase(adev, true);
3659 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003660 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003661 out->stream.set_callback = out_set_callback;
3662 out->stream.pause = out_pause;
3663 out->stream.resume = out_resume;
3664 out->stream.drain = out_drain;
3665 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003666 out->usecase = get_offload_usecase(adev, false);
3667 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003668 }
vivek mehta446c3962015-09-14 10:57:35 -07003669
3670 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003671 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3672 config->format == 0 && config->sample_rate == 0 &&
3673 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003674 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003675 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3676 } else {
3677 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3678 ret = -EEXIST;
3679 goto error_open;
3680 }
vivek mehta446c3962015-09-14 10:57:35 -07003681 }
3682
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003683 if (config->offload_info.channel_mask)
3684 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003685 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003686 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003687 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003688 } else {
3689 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3690 ret = -EINVAL;
3691 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003692 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003693
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003694 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003695 out->sample_rate = config->offload_info.sample_rate;
3696
Mingming Yin3ee55c62014-08-04 14:23:35 -07003697 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303699 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3700 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3701 audio_extn_dolby_send_ddp_endp_params(adev);
3702 audio_extn_dolby_set_dmid(adev);
3703 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003704
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003705 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003706 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003707 out->compr_config.codec->bit_rate =
3708 config->offload_info.bit_rate;
3709 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303710 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003711 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303712 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003713 /*TODO: Do we need to change it for passthrough */
3714 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003715
Manish Dewangana6fc5442015-08-24 20:30:31 +05303716 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3717 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3718 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3719 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303720
3721 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3722 AUDIO_FORMAT_PCM) {
3723
3724 /*Based on platform support, configure appropriate alsa format for corresponding
3725 *hal input format.
3726 */
3727 out->compr_config.codec->format = hal_format_to_alsa(
3728 config->offload_info.format);
3729
Ashish Jain83a6cc22016-06-28 14:34:17 +05303730 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303731 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303732 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303733
3734 /*for direct PCM playback populate bit_width based on selected alsa format as
3735 *hal input format and alsa format might differ based on platform support.
3736 */
3737 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303738 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303739
3740 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3741
3742 /* Check if alsa session is configured with the same format as HAL input format,
3743 * if not then derive correct fragment size needed to accomodate the
3744 * conversion of HAL input format to alsa format.
3745 */
3746 audio_extn_utils_update_direct_pcm_fragment_size(out);
3747
3748 /*if hal input and output fragment size is different this indicates HAL input format is
3749 *not same as the alsa format
3750 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303751 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303752 /*Allocate a buffer to convert input data to the alsa configured format.
3753 *size of convert buffer is equal to the size required to hold one fragment size
3754 *worth of pcm data, this is because flinger does not write more than fragment_size
3755 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303756 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3757 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303758 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3759 ret = -ENOMEM;
3760 goto error_open;
3761 }
3762 }
3763 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3764 out->compr_config.fragment_size =
3765 audio_extn_passthru_get_buffer_size(&config->offload_info);
3766 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3767 } else {
3768 out->compr_config.fragment_size =
3769 platform_get_compress_offload_buffer_size(&config->offload_info);
3770 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3771 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003772
Amit Shekhar6f461b12014-08-01 14:52:58 -07003773 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303774 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003775
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003776 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3777 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003778
Alexy Josephaa54c872014-12-03 02:46:47 -08003779
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003780 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303781 out->send_next_track_params = false;
3782 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003783 out->offload_state = OFFLOAD_STATE_IDLE;
3784 out->playback_started = 0;
3785
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003786 audio_extn_dts_create_state_notifier_node(out->usecase);
3787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003788 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3789 __func__, config->offload_info.version,
3790 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303791
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303792 /* Check if DSD audio format is supported in codec
3793 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303794 */
3795
3796 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303797 (!platform_check_codec_dsd_support(adev->platform) ||
3798 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303799 ret = -EINVAL;
3800 goto error_open;
3801 }
3802
Ashish Jain5106d362016-05-11 19:23:33 +05303803 /* Disable gapless if any of the following is true
3804 * passthrough playback
3805 * AV playback
3806 * Direct PCM playback
3807 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303808 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303809 (config->format == AUDIO_FORMAT_DSD) ||
3810 config->offload_info.has_video ||
3811 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303812 check_and_set_gapless_mode(adev, false);
3813 } else
3814 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003815
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303816 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003817 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3818 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303819 if (config->format == AUDIO_FORMAT_DSD) {
3820 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3821 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3822 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003823
3824 create_offload_callback_thread(out);
3825
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003826 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303827 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003828 if (ret != 0) {
3829 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3830 __func__, ret);
3831 goto error_open;
3832 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003833 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3834 if (config->sample_rate == 0)
3835 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3836 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3837 config->sample_rate != 8000) {
3838 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3839 ret = -EINVAL;
3840 goto error_open;
3841 }
3842 out->sample_rate = config->sample_rate;
3843 out->config.rate = config->sample_rate;
3844 if (config->format == AUDIO_FORMAT_DEFAULT)
3845 config->format = AUDIO_FORMAT_PCM_16_BIT;
3846 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3847 config->format = AUDIO_FORMAT_PCM_16_BIT;
3848 ret = -EINVAL;
3849 goto error_open;
3850 }
3851 out->format = config->format;
3852 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3853 out->config = pcm_config_afe_proxy_playback;
3854 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003855 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303856 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3857 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003858 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3859 out->flags);
3860 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303861 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3862 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3863 out->config = pcm_config_low_latency;
3864 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3865 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3866 out->config = pcm_config_deep_buffer;
3867 } else {
3868 /* primary path is the default path selected if no other outputs are available/suitable */
3869 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3870 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3871 }
3872 out->hal_ip_format = format = out->format;
3873 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3874 out->hal_op_format = pcm_format_to_hal(out->config.format);
3875 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3876 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003877 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303878 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3879 if (out->hal_ip_format != out->hal_op_format) {
3880 uint32_t buffer_size = out->config.period_size *
3881 format_to_bitwidth_table[out->hal_op_format] *
3882 out->config.channels;
3883 out->convert_buffer = calloc(1, buffer_size);
3884 if (out->convert_buffer == NULL){
3885 ALOGE("Allocation failed for convert buffer for size %d",
3886 out->compr_config.fragment_size);
3887 ret = -ENOMEM;
3888 goto error_open;
3889 }
3890 ALOGD("Convert buffer allocated of size %d", buffer_size);
3891 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892 }
3893
Ashish Jain83a6cc22016-06-28 14:34:17 +05303894 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3895 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3896
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003897 /* TODO remove this hardcoding and check why width is zero*/
3898 if (out->bit_width == 0)
3899 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003900 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3901 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003902 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303903 out->bit_width, out->channel_mask,
3904 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003905 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3906 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3907 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003908 if(adev->primary_output == NULL)
3909 adev->primary_output = out;
3910 else {
3911 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003912 ret = -EEXIST;
3913 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003914 }
3915 }
3916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 /* Check if this usecase is already existing */
3918 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003919 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3920 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003923 ret = -EEXIST;
3924 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 }
3926 pthread_mutex_unlock(&adev->lock);
3927
3928 out->stream.common.get_sample_rate = out_get_sample_rate;
3929 out->stream.common.set_sample_rate = out_set_sample_rate;
3930 out->stream.common.get_buffer_size = out_get_buffer_size;
3931 out->stream.common.get_channels = out_get_channels;
3932 out->stream.common.get_format = out_get_format;
3933 out->stream.common.set_format = out_set_format;
3934 out->stream.common.standby = out_standby;
3935 out->stream.common.dump = out_dump;
3936 out->stream.common.set_parameters = out_set_parameters;
3937 out->stream.common.get_parameters = out_get_parameters;
3938 out->stream.common.add_audio_effect = out_add_audio_effect;
3939 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3940 out->stream.get_latency = out_get_latency;
3941 out->stream.set_volume = out_set_volume;
3942 out->stream.write = out_write;
3943 out->stream.get_render_position = out_get_render_position;
3944 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003945 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003947 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003949 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003950 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951
3952 config->format = out->stream.common.get_format(&out->stream.common);
3953 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3954 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3955
3956 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303957 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003958 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003959
3960 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3961 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3962 popcount(out->channel_mask), out->playback_started);
3963
Eric Laurent994a6932013-07-17 11:51:42 -07003964 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003966
3967error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303968 if (out->convert_buffer)
3969 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003970 free(out);
3971 *stream_out = NULL;
3972 ALOGD("%s: exit: ret %d", __func__, ret);
3973 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974}
3975
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303976void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 struct audio_stream_out *stream)
3978{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979 struct stream_out *out = (struct stream_out *)stream;
3980 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003981 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303983 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3984
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003985 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303986 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003987 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303988 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003989 if(ret != 0)
3990 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3991 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003992 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003993 out_standby(&stream->common);
3994
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003995 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003996 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003997 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003998 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003999 if (out->compr_config.codec != NULL)
4000 free(out->compr_config.codec);
4001 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004002
Ashish Jain83a6cc22016-06-28 14:34:17 +05304003 if (out->convert_buffer != NULL) {
4004 free(out->convert_buffer);
4005 out->convert_buffer = NULL;
4006 }
4007
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004008 if (adev->voice_tx_output == out)
4009 adev->voice_tx_output = NULL;
4010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004011 pthread_cond_destroy(&out->cond);
4012 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004014 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015}
4016
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004017static void close_compress_sessions(struct audio_device *adev)
4018{
Mingming Yin7b762e72015-03-04 13:47:32 -08004019 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304020 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004021 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004022 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304023
4024 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004025 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304026 if (is_offload_usecase(usecase->id)) {
4027 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004028 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4029 out = usecase->stream.out;
4030 pthread_mutex_unlock(&adev->lock);
4031 out_standby(&out->stream.common);
4032 pthread_mutex_lock(&adev->lock);
4033 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304034 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004035 }
4036 pthread_mutex_unlock(&adev->lock);
4037}
4038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4040{
4041 struct audio_device *adev = (struct audio_device *)dev;
4042 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004044 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004045 int ret;
4046 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004048 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304051 if (!parms)
4052 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004053 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4054 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304055 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304056 if (strstr(snd_card_status, "OFFLINE")) {
4057 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304058 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004059 //close compress sessions on OFFLINE status
4060 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304061 } else if (strstr(snd_card_status, "ONLINE")) {
4062 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304063 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004064 //send dts hpx license if enabled
4065 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304066 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304067 }
4068
4069 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004070 status = voice_set_parameters(adev, parms);
4071 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004072 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004074 status = platform_set_parameters(adev->platform, parms);
4075 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004076 goto done;
4077
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004078 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4079 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004080 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4082 adev->bluetooth_nrec = true;
4083 else
4084 adev->bluetooth_nrec = false;
4085 }
4086
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004087 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4088 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4090 adev->screen_off = false;
4091 else
4092 adev->screen_off = true;
4093 }
4094
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004095 ret = str_parms_get_int(parms, "rotation", &val);
4096 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004097 bool reverse_speakers = false;
4098 switch(val) {
4099 // FIXME: note that the code below assumes that the speakers are in the correct placement
4100 // relative to the user when the device is rotated 90deg from its default rotation. This
4101 // assumption is device-specific, not platform-specific like this code.
4102 case 270:
4103 reverse_speakers = true;
4104 break;
4105 case 0:
4106 case 90:
4107 case 180:
4108 break;
4109 default:
4110 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004111 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004112 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004113 if (status == 0) {
4114 if (adev->speaker_lr_swap != reverse_speakers) {
4115 adev->speaker_lr_swap = reverse_speakers;
4116 // only update the selected device if there is active pcm playback
4117 struct audio_usecase *usecase;
4118 struct listnode *node;
4119 list_for_each(node, &adev->usecase_list) {
4120 usecase = node_to_item(node, struct audio_usecase, list);
4121 if (usecase->type == PCM_PLAYBACK) {
4122 select_devices(adev, usecase->id);
4123 break;
4124 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004125 }
4126 }
4127 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004128 }
4129
Mingming Yin514a8bc2014-07-29 15:22:21 -07004130 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4131 if (ret >= 0) {
4132 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4133 adev->bt_wb_speech_enabled = true;
4134 else
4135 adev->bt_wb_speech_enabled = false;
4136 }
4137
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004138 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4139 if (ret >= 0) {
4140 val = atoi(value);
4141 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004142 ALOGV("cache new ext disp type and edid");
4143 ret = platform_get_ext_disp_type(adev->platform);
4144 if (ret < 0) {
4145 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4146 return ret;
4147 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004148 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004149 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004150 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004151 /*
4152 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4153 * Per AudioPolicyManager, USB device is higher priority than WFD.
4154 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4155 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4156 * starting voice call on USB
4157 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004158 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4159 if (ret >= 0) {
4160 audio_extn_usb_add_device(val, atoi(value));
4161 }
vivek mehta344576a2016-04-12 18:56:03 -07004162 ALOGV("detected USB connect .. disable proxy");
4163 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004164 }
4165 }
4166
4167 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4168 if (ret >= 0) {
4169 val = atoi(value);
4170 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4171 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004172 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004173 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004174 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004175 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4176 if (ret >= 0) {
4177 audio_extn_usb_remove_device(val, atoi(value));
4178 }
vivek mehta344576a2016-04-12 18:56:03 -07004179 ALOGV("detected USB disconnect .. enable proxy");
4180 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004181 }
4182 }
4183
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304184 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4185 if (ret >= 0) {
4186 struct audio_usecase *usecase;
4187 struct listnode *node;
4188 list_for_each(node, &adev->usecase_list) {
4189 usecase = node_to_item(node, struct audio_usecase, list);
4190 if ((usecase->type == PCM_PLAYBACK) &&
4191 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4192 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304193 lock_output_stream(usecase->stream.out);
4194 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304195 //force device switch to re configure encoder
4196 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304197 audio_extn_a2dp_set_handoff_mode(false);
4198 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304199 break;
4200 }
4201 }
4202 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304203 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004204done:
4205 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004206 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304207error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004208 ALOGV("%s: exit with code(%d)", __func__, status);
4209 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210}
4211
4212static char* adev_get_parameters(const struct audio_hw_device *dev,
4213 const char *keys)
4214{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004215 struct audio_device *adev = (struct audio_device *)dev;
4216 struct str_parms *reply = str_parms_create();
4217 struct str_parms *query = str_parms_create_str(keys);
4218 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304219 char value[256] = {0};
4220 int ret = 0;
4221
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004222 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004223 if (reply) {
4224 str_parms_destroy(reply);
4225 }
4226 if (query) {
4227 str_parms_destroy(query);
4228 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004229 ALOGE("adev_get_parameters: failed to create query or reply");
4230 return NULL;
4231 }
4232
Naresh Tannirud7205b62014-06-20 02:54:48 +05304233 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4234 sizeof(value));
4235 if (ret >=0) {
4236 int val = 1;
4237 pthread_mutex_lock(&adev->snd_card_status.lock);
4238 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4239 val = 0;
4240 pthread_mutex_unlock(&adev->snd_card_status.lock);
4241 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4242 goto exit;
4243 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004244
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004245 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004246 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004247 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004248 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304249 pthread_mutex_unlock(&adev->lock);
4250
Naresh Tannirud7205b62014-06-20 02:54:48 +05304251exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004252 str = str_parms_to_str(reply);
4253 str_parms_destroy(query);
4254 str_parms_destroy(reply);
4255
4256 ALOGV("%s: exit: returns - %s", __func__, str);
4257 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258}
4259
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004260static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261{
4262 return 0;
4263}
4264
4265static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4266{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004267 int ret;
4268 struct audio_device *adev = (struct audio_device *)dev;
4269 pthread_mutex_lock(&adev->lock);
4270 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004271 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004272 pthread_mutex_unlock(&adev->lock);
4273 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274}
4275
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004276static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4277 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278{
4279 return -ENOSYS;
4280}
4281
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004282static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4283 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284{
4285 return -ENOSYS;
4286}
4287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004288static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4289 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290{
4291 return -ENOSYS;
4292}
4293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004294static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4295 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296{
4297 return -ENOSYS;
4298}
4299
4300static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4301{
4302 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 pthread_mutex_lock(&adev->lock);
4305 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004306 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004308 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004309 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004310 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004311 adev->current_call_output = NULL;
4312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 }
4314 pthread_mutex_unlock(&adev->lock);
4315 return 0;
4316}
4317
4318static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4319{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004320 int ret;
4321
4322 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004323 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004324 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4325 pthread_mutex_unlock(&adev->lock);
4326
4327 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328}
4329
4330static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4331{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004332 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 return 0;
4334}
4335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004336static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 const struct audio_config *config)
4338{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004339 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004341 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4342 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343}
4344
4345static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004346 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 audio_devices_t devices,
4348 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004349 struct audio_stream_in **stream_in,
4350 audio_input_flags_t flags __unused,
4351 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004352 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353{
4354 struct audio_device *adev = (struct audio_device *)dev;
4355 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004356 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004357 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004358 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304361 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4362 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365
4366 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004367
4368 if (!in) {
4369 ALOGE("failed to allocate input stream");
4370 return -ENOMEM;
4371 }
4372
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304373 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304374 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4375 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004376 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004377 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 in->stream.common.get_sample_rate = in_get_sample_rate;
4380 in->stream.common.set_sample_rate = in_set_sample_rate;
4381 in->stream.common.get_buffer_size = in_get_buffer_size;
4382 in->stream.common.get_channels = in_get_channels;
4383 in->stream.common.get_format = in_get_format;
4384 in->stream.common.set_format = in_set_format;
4385 in->stream.common.standby = in_standby;
4386 in->stream.common.dump = in_dump;
4387 in->stream.common.set_parameters = in_set_parameters;
4388 in->stream.common.get_parameters = in_get_parameters;
4389 in->stream.common.add_audio_effect = in_add_audio_effect;
4390 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4391 in->stream.set_gain = in_set_gain;
4392 in->stream.read = in_read;
4393 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4394
4395 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004396 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398 in->standby = 1;
4399 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004400 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004401 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402
4403 /* Update config params with the requested sample rate and channels */
4404 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004405 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4406 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4407 is_low_latency = true;
4408#if LOW_LATENCY_CAPTURE_USE_CASE
4409 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4410#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004411 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004412 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004413
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004414 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004415 if (in->realtime) {
4416 in->config = pcm_config_audio_capture_rt;
4417 in->sample_rate = in->config.rate;
4418 in->af_period_multiplier = af_period_multiplier;
4419 } else {
4420 in->config = pcm_config_audio_capture;
4421 in->config.rate = config->sample_rate;
4422 in->sample_rate = config->sample_rate;
4423 in->af_period_multiplier = 1;
4424 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304425 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004427 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304428 if (adev->mode != AUDIO_MODE_IN_CALL) {
4429 ret = -EINVAL;
4430 goto err_open;
4431 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004432 if (config->sample_rate == 0)
4433 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4434 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4435 config->sample_rate != 8000) {
4436 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4437 ret = -EINVAL;
4438 goto err_open;
4439 }
4440 if (config->format == AUDIO_FORMAT_DEFAULT)
4441 config->format = AUDIO_FORMAT_PCM_16_BIT;
4442 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4443 config->format = AUDIO_FORMAT_PCM_16_BIT;
4444 ret = -EINVAL;
4445 goto err_open;
4446 }
4447
4448 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4449 in->config = pcm_config_afe_proxy_record;
4450 in->config.channels = channel_count;
4451 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304452 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304453 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4454 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004455 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004456 audio_extn_compr_cap_format_supported(config->format) &&
4457 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004458 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004459 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304460 /* restrict 24 bit capture for unprocessed source only
4461 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4462 */
4463 if (config->format == AUDIO_FORMAT_DEFAULT) {
4464 config->format = AUDIO_FORMAT_PCM_16_BIT;
4465 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4466 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4467 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4468 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4469 bool ret_error = false;
4470 in->bit_width = 24;
4471 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4472 from HAL is 24_packed and 8_24
4473 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4474 24_packed return error indicating supported format is 24_packed
4475 *> In case of any other source requesting 24 bit or float return error
4476 indicating format supported is 16 bit only.
4477
4478 on error flinger will retry with supported format passed
4479 */
4480 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4481 (source != AUDIO_SOURCE_CAMCORDER)) {
4482 config->format = AUDIO_FORMAT_PCM_16_BIT;
4483 if( config->sample_rate > 48000)
4484 config->sample_rate = 48000;
4485 ret_error = true;
4486 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4487 in->config.format = PCM_FORMAT_S24_3LE;
4488 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4489 in->config.format = PCM_FORMAT_S24_LE;
4490 } else {
4491 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4492 ret_error = true;
4493 }
4494
4495 if (ret_error) {
4496 ret = -EINVAL;
4497 goto err_open;
4498 }
4499 }
4500
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004501 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004502 if (!in->realtime) {
4503 in->format = config->format;
4504 frame_size = audio_stream_in_frame_size(&in->stream);
4505 buffer_size = get_input_buffer_size(config->sample_rate,
4506 config->format,
4507 channel_count,
4508 is_low_latency);
4509 in->config.period_size = buffer_size / frame_size;
4510 }
4511
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004512 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4513 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4514 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004515 (in->config.rate == 8000 || in->config.rate == 16000 ||
4516 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004517 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4518 voice_extn_compress_voip_open_input_stream(in);
4519 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004522 /* This stream could be for sound trigger lab,
4523 get sound trigger pcm if present */
4524 audio_extn_sound_trigger_check_and_get_session(in);
4525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004527 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004528 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529
4530err_open:
4531 free(in);
4532 *stream_in = NULL;
4533 return ret;
4534}
4535
4536static void adev_close_input_stream(struct audio_hw_device *dev,
4537 struct audio_stream_in *stream)
4538{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004539 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004540 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004541 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304543 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004544
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304545 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004546 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304547
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004548 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304549 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004550 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304551 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004552 if (ret != 0)
4553 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4554 __func__, ret);
4555 } else
4556 in_standby(&stream->common);
4557
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004558 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004559 audio_extn_ssr_deinit();
4560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561
Mingming Yine62d7842013-10-25 16:26:03 -07004562 if(audio_extn_compr_cap_enabled() &&
4563 audio_extn_compr_cap_format_supported(in->config.format))
4564 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004565
Mingming Yinfd7607b2016-01-22 12:48:44 -08004566 if (in->is_st_session) {
4567 ALOGV("%s: sound trigger pcm stop lab", __func__);
4568 audio_extn_sound_trigger_stop_lab(in);
4569 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004570 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571 return;
4572}
4573
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004574static int adev_dump(const audio_hw_device_t *device __unused,
4575 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576{
4577 return 0;
4578}
4579
4580static int adev_close(hw_device_t *device)
4581{
4582 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004583
4584 if (!adev)
4585 return 0;
4586
4587 pthread_mutex_lock(&adev_init_lock);
4588
4589 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004590 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004591 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304592 if (audio_extn_qaf_is_enabled())
4593 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004594 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004595 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004596 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004597 free(adev->snd_dev_ref_cnt);
4598 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004599 if (adev->adm_deinit)
4600 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004601 free(device);
4602 adev = NULL;
4603 }
4604 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return 0;
4607}
4608
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004609/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4610 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4611 * just that it _might_ work.
4612 */
4613static int period_size_is_plausible_for_low_latency(int period_size)
4614{
4615 switch (period_size) {
4616 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004617 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004618 case 240:
4619 case 320:
4620 case 480:
4621 return 1;
4622 default:
4623 return 0;
4624 }
4625}
4626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627static int adev_open(const hw_module_t *module, const char *name,
4628 hw_device_t **device)
4629{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304630 int ret;
4631
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004632 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4634
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004635 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004636 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004637 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004638 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004639 ALOGD("%s: returning existing instance of adev", __func__);
4640 ALOGD("%s: exit", __func__);
4641 pthread_mutex_unlock(&adev_init_lock);
4642 return 0;
4643 }
4644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 adev = calloc(1, sizeof(struct audio_device));
4646
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004647 if (!adev) {
4648 pthread_mutex_unlock(&adev_init_lock);
4649 return -ENOMEM;
4650 }
4651
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004652 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4655 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4656 adev->device.common.module = (struct hw_module_t *)module;
4657 adev->device.common.close = adev_close;
4658
4659 adev->device.init_check = adev_init_check;
4660 adev->device.set_voice_volume = adev_set_voice_volume;
4661 adev->device.set_master_volume = adev_set_master_volume;
4662 adev->device.get_master_volume = adev_get_master_volume;
4663 adev->device.set_master_mute = adev_set_master_mute;
4664 adev->device.get_master_mute = adev_get_master_mute;
4665 adev->device.set_mode = adev_set_mode;
4666 adev->device.set_mic_mute = adev_set_mic_mute;
4667 adev->device.get_mic_mute = adev_get_mic_mute;
4668 adev->device.set_parameters = adev_set_parameters;
4669 adev->device.get_parameters = adev_get_parameters;
4670 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4671 adev->device.open_output_stream = adev_open_output_stream;
4672 adev->device.close_output_stream = adev_close_output_stream;
4673 adev->device.open_input_stream = adev_open_input_stream;
4674 adev->device.close_input_stream = adev_close_input_stream;
4675 adev->device.dump = adev_dump;
4676
4677 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004679 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004680 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004683 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004684 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004685 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004686 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004687 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004688 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004689 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004690 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304691 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304692 adev->perf_lock_opts[0] = 0x101;
4693 adev->perf_lock_opts[1] = 0x20E;
4694 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304695
4696 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4697 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004699 adev->platform = platform_init(adev);
4700 if (!adev->platform) {
4701 free(adev->snd_dev_ref_cnt);
4702 free(adev);
4703 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4704 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004705 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304706 pthread_mutex_destroy(&adev->lock);
4707 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004708 return -EINVAL;
4709 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004710
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304711 if (audio_extn_qaf_is_enabled()) {
4712 ret = audio_extn_qaf_init(adev);
4713 if (ret < 0) {
4714 free(adev);
4715 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4716 *device = NULL;
4717 pthread_mutex_unlock(&adev_init_lock);
4718 pthread_mutex_destroy(&adev->lock);
4719 return ret;
4720 }
4721
4722 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4723 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4724 }
4725
Naresh Tanniru4c630392014-05-12 01:05:52 +05304726 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4727
Eric Laurentc4aef752013-09-12 17:45:53 -07004728 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4729 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4730 if (adev->visualizer_lib == NULL) {
4731 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4732 } else {
4733 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4734 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004735 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004736 "visualizer_hal_start_output");
4737 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004738 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004739 "visualizer_hal_stop_output");
4740 }
4741 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004742 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004743 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004744 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004745
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004746 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4747 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4748 if (adev->offload_effects_lib == NULL) {
4749 ALOGE("%s: DLOPEN failed for %s", __func__,
4750 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4751 } else {
4752 ALOGV("%s: DLOPEN successful for %s", __func__,
4753 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4754 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304755 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004756 "offload_effects_bundle_hal_start_output");
4757 adev->offload_effects_stop_output =
4758 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4759 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004760 adev->offload_effects_set_hpx_state =
4761 (int (*)(bool))dlsym(adev->offload_effects_lib,
4762 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304763 adev->offload_effects_get_parameters =
4764 (void (*)(struct str_parms *, struct str_parms *))
4765 dlsym(adev->offload_effects_lib,
4766 "offload_effects_bundle_get_parameters");
4767 adev->offload_effects_set_parameters =
4768 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4769 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004770 }
4771 }
4772
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004773 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4774 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4775 if (adev->adm_lib == NULL) {
4776 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4777 } else {
4778 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4779 adev->adm_init = (adm_init_t)
4780 dlsym(adev->adm_lib, "adm_init");
4781 adev->adm_deinit = (adm_deinit_t)
4782 dlsym(adev->adm_lib, "adm_deinit");
4783 adev->adm_register_input_stream = (adm_register_input_stream_t)
4784 dlsym(adev->adm_lib, "adm_register_input_stream");
4785 adev->adm_register_output_stream = (adm_register_output_stream_t)
4786 dlsym(adev->adm_lib, "adm_register_output_stream");
4787 adev->adm_deregister_stream = (adm_deregister_stream_t)
4788 dlsym(adev->adm_lib, "adm_deregister_stream");
4789 adev->adm_request_focus = (adm_request_focus_t)
4790 dlsym(adev->adm_lib, "adm_request_focus");
4791 adev->adm_abandon_focus = (adm_abandon_focus_t)
4792 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004793 adev->adm_set_config = (adm_set_config_t)
4794 dlsym(adev->adm_lib, "adm_set_config");
4795 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4796 dlsym(adev->adm_lib, "adm_request_focus_v2");
4797 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4798 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4799 adev->adm_on_routing_change = (adm_on_routing_change_t)
4800 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004801 }
4802 }
4803
Mingming Yin514a8bc2014-07-29 15:22:21 -07004804 adev->bt_wb_speech_enabled = false;
4805
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004806 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807 *device = &adev->device.common;
4808
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004809 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4810 &adev->streams_output_cfg_list);
4811
Kiran Kandi910e1862013-10-29 13:29:42 -07004812 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004813
4814 char value[PROPERTY_VALUE_MAX];
4815 int trial;
4816 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4817 trial = atoi(value);
4818 if (period_size_is_plausible_for_low_latency(trial)) {
4819 pcm_config_low_latency.period_size = trial;
4820 pcm_config_low_latency.start_threshold = trial / 4;
4821 pcm_config_low_latency.avail_min = trial / 4;
4822 configured_low_latency_capture_period_size = trial;
4823 }
4824 }
4825 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4826 trial = atoi(value);
4827 if (period_size_is_plausible_for_low_latency(trial)) {
4828 configured_low_latency_capture_period_size = trial;
4829 }
4830 }
4831
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004832 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4833 af_period_multiplier = atoi(value);
4834 if (af_period_multiplier < 0)
4835 af_period_multiplier = 2;
4836 else if (af_period_multiplier > 4)
4837 af_period_multiplier = 4;
4838
4839 ALOGV("new period_multiplier = %d", af_period_multiplier);
4840 }
4841
vivek mehta446c3962015-09-14 10:57:35 -07004842 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004843 pthread_mutex_unlock(&adev_init_lock);
4844
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004845 if (adev->adm_init)
4846 adev->adm_data = adev->adm_init();
4847
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304848 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004849 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 return 0;
4851}
4852
4853static struct hw_module_methods_t hal_module_methods = {
4854 .open = adev_open,
4855};
4856
4857struct audio_module HAL_MODULE_INFO_SYM = {
4858 .common = {
4859 .tag = HARDWARE_MODULE_TAG,
4860 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4861 .hal_api_version = HARDWARE_HAL_API_VERSION,
4862 .id = AUDIO_HARDWARE_MODULE_ID,
4863 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004864 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 .methods = &hal_module_methods,
4866 },
4867};