blob: e85e84c445cd1954cd81f6c3360c53ef65f693e0 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625/*
626 * Enable ASRC mode if native or DSD stream is active.
627 */
628static void audio_check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
629{
630 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635
636 list_for_each(node, &adev->usecase_list) {
637 uc = node_to_item(node, struct audio_usecase, list);
638 curr_out = (struct stream_out*) uc->stream.out;
639
640 if (curr_out && PCM_PLAYBACK == uc->type) {
641 if((platform_get_backend_index(uc->out_snd_device) == HEADPHONE_44_1_BACKEND) ||
642 (platform_get_backend_index(uc->out_snd_device) == DSD_NATIVE_BACKEND)) {
643 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
644 __func__);
645 audio_route_apply_and_update_path(adev->audio_route,
646 "asrc-mode");
647 adev->asrc_mode_enabled = true;
648 break;
649 }
650 }
651 }
652 }
653}
654
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700655int pcm_ioctl(struct pcm *pcm, int request, ...)
656{
657 va_list ap;
658 void * arg;
659 int pcm_fd = *(int*)pcm;
660
661 va_start(ap, request);
662 arg = va_arg(ap, void *);
663 va_end(ap);
664
665 return ioctl(pcm_fd, request, arg);
666}
667
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700668int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700672 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800673
674 if (usecase == NULL)
675 return -EINVAL;
676
677 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
678
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800684#ifdef DS1_DOLBY_DAP_ENABLED
685 audio_extn_dolby_set_dmid(adev);
686 audio_extn_dolby_set_endpoint(adev);
687#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700688 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700689 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530690 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700691 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530692 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800693 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700694 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700695 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700696 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 ALOGV("%s: exit", __func__);
698 return 0;
699}
700
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700701int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530707 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 if (usecase->type == PCM_CAPTURE)
712 snd_device = usecase->in_snd_device;
713 else
714 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800715 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700716 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700717 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700718 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700719 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530720 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 ALOGV("%s: exit", __func__);
722 return 0;
723}
724
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700725int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700726 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530728 int i, num_devices = 0;
729 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700730 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
731
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800732 if (snd_device < SND_DEVICE_MIN ||
733 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800734 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800735 return -EINVAL;
736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737
738 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700739
740 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
741 ALOGE("%s: Invalid sound device returned", __func__);
742 return -EINVAL;
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700745 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700746 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 return 0;
748 }
749
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530750
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700751 if (audio_extn_spkr_prot_is_enabled())
752 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700753
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800754 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
755 audio_extn_spkr_prot_is_enabled()) {
756 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700757 adev->snd_dev_ref_cnt[snd_device]--;
758 return -EINVAL;
759 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200760 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800761 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800762 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200763 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 return -EINVAL;
765 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530766 } else if (platform_can_split_snd_device(adev->platform, snd_device,
767 &num_devices, new_snd_devices)) {
768 for (i = 0; i < num_devices; i++) {
769 enable_snd_device(adev, new_snd_devices[i]);
770 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800771 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530773
774 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
775 (audio_extn_a2dp_start_playback() < 0)) {
776 ALOGE(" fail to configure A2dp control path ");
777 return -EINVAL;
778 }
779
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700780 /* due to the possibility of calibration overwrite between listen
781 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700782 audio_extn_sound_trigger_update_device_status(snd_device,
783 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530784 audio_extn_listen_update_device_status(snd_device,
785 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700786 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 audio_extn_sound_trigger_update_device_status(snd_device,
789 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530790 audio_extn_listen_update_device_status(snd_device,
791 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700792 return -EINVAL;
793 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300794 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700795 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
797 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
798 !adev->native_playback_enabled &&
799 audio_is_true_native_stream_active(adev)) {
800 ALOGD("%s: %d: napb: enabling native mode in hardware",
801 __func__, __LINE__);
802 audio_route_apply_and_update_path(adev->audio_route,
803 "true-native-mode");
804 adev->native_playback_enabled = true;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530805 } else
806 audio_check_and_set_asrc_mode(adev, snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700812 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530814 int i, num_devices = 0;
815 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700816 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
817
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800818 if (snd_device < SND_DEVICE_MIN ||
819 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 return -EINVAL;
822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
824 ALOGE("%s: device ref cnt is already 0", __func__);
825 return -EINVAL;
826 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700827
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700829
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
831 ALOGE("%s: Invalid sound device returned", __func__);
832 return -EINVAL;
833 }
834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700836 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530837
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800838 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
839 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700840 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530841 } else if (platform_can_split_snd_device(adev->platform, snd_device,
842 &num_devices, new_snd_devices)) {
843 for (i = 0; i < num_devices; i++) {
844 disable_snd_device(adev, new_snd_devices[i]);
845 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300846 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700847 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300848 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700849
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530850 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
851 audio_extn_a2dp_stop_playback();
852
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700853 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530854 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530855 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 adev->native_playback_enabled) {
857 ALOGD("%s: %d: napb: disabling native mode in hardware",
858 __func__, __LINE__);
859 audio_route_reset_and_update_path(adev->audio_route,
860 "true-native-mode");
861 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530862 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
863 adev->asrc_mode_enabled) {
864 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
865 audio_route_reset_and_update_path(adev->audio_route, "asrc-mode");
866 adev->asrc_mode_enabled = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530868
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200869 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700870 audio_extn_sound_trigger_update_device_status(snd_device,
871 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530872 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800873 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 return 0;
877}
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530880 struct audio_usecase *uc_info,
881 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882{
883 struct listnode *node;
884 struct audio_usecase *usecase;
885 bool switch_device[AUDIO_USECASE_MAX];
886 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530887 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 /*
889 * This function is to make sure that all the usecases that are active on
890 * the hardware codec backend are always routed to any one device that is
891 * handled by the hardware codec.
892 * For example, if low-latency and deep-buffer usecases are currently active
893 * on speaker and out_set_parameters(headset) is received on low-latency
894 * output, then we have to make sure deep-buffer is also switched to headset,
895 * because of the limitation that both the devices cannot be enabled
896 * at the same time as they share the same backend.
897 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700898 /*
899 * This call is to check if we need to force routing for a particular stream
900 * If there is a backend configuration change for the device when a
901 * new stream starts, then ADM needs to be closed and re-opened with the new
902 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800903 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700904 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800905 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
906 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
912 audio_extn_a2dp_is_force_device_switch()) {
913 force_routing = true;
914 force_restart_session = true;
915 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 ALOGD("%s:becf: force routing %d", __func__, force_routing);
917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800919 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800920 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 for (i = 0; i < AUDIO_USECASE_MAX; i++)
922 switch_device[i] = false;
923
924 list_for_each(node, &adev->usecase_list) {
925 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800926
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530927 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
928 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530929 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530930 platform_get_snd_device_name(usecase->out_snd_device),
931 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800932 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530933 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530934 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530935 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
936 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530937 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530938 (force_restart_session)) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530939 (platform_check_backends_match(snd_device, usecase->out_snd_device)||
940 (platform_check_codec_asrc_support(adev->platform) && !adev->asrc_mode_enabled &&
941 platform_check_if_backend_has_to_be_disabled(snd_device,usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530942 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
944 platform_get_snd_device_name(usecase->out_snd_device));
945 disable_audio_route(adev, usecase);
946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530951 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
952 num_uc_to_switch);
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700955 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530957 /* Make sure the previous devices to be disabled first and then enable the
958 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 }
964 }
965
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700970 }
971 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 /* Re-route all the usecases on the shared backend other than the
974 specified usecase to new snd devices */
975 list_for_each(node, &adev->usecase_list) {
976 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530977 /* Update the out_snd_device only before enabling the audio route */
978 if (switch_device[usecase->id]) {
979 usecase->out_snd_device = snd_device;
980 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530981 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530982 use_case_table[usecase->id],
983 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 }
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989}
990
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530991static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 struct audio_usecase *uc_info,
993 snd_device_t snd_device)
994{
995 struct listnode *node;
996 struct audio_usecase *usecase;
997 bool switch_device[AUDIO_USECASE_MAX];
998 int i, num_uc_to_switch = 0;
999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301000 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1001 snd_device);
1002 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001018 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301020 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001021 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301022 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001023 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001024 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001025 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1026 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001027 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001028 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001029 switch_device[usecase->id] = true;
1030 num_uc_to_switch++;
1031 }
1032 }
1033
1034 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001035 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301037 /* Make sure the previous devices to be disabled first and then enable the
1038 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001043 }
1044 }
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001049 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 }
1051 }
1052
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001053 /* Re-route all the usecases on the shared backend other than the
1054 specified usecase to new snd devices */
1055 list_for_each(node, &adev->usecase_list) {
1056 usecase = node_to_item(node, struct audio_usecase, list);
1057 /* Update the in_snd_device only before enabling the audio route */
1058 if (switch_device[usecase->id] ) {
1059 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001060 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301061 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001062 }
1063 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001064 }
1065}
1066
Mingming Yin3a941d42016-02-17 18:08:05 -08001067static void reset_hdmi_sink_caps(struct stream_out *out) {
1068 int i = 0;
1069
1070 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1071 out->supported_channel_masks[i] = 0;
1072 }
1073 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1074 out->supported_formats[i] = 0;
1075 }
1076 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1077 out->supported_sample_rates[i] = 0;
1078 }
1079}
1080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001082static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083{
Mingming Yin3a941d42016-02-17 18:08:05 -08001084 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001085 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086
Mingming Yin3a941d42016-02-17 18:08:05 -08001087 reset_hdmi_sink_caps(out);
1088
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001089 /* Cache ext disp type */
1090 ret = platform_get_ext_disp_type(adev->platform);
1091 if (ret < 0) {
1092 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1093 return ret;
1094 }
1095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001098 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001099 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001100 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1101 case 6:
1102 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1103 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1104 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1105 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1106 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1107 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 break;
1109 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001110 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001111 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 break;
1113 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001114
1115 // check channel format caps
1116 i = 0;
1117 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1118 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1119 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1120 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1121 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1122 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1123 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1124 }
1125
1126 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1127 ALOGV(":%s HDMI supports DTS format", __func__);
1128 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1129 }
1130
1131 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1132 ALOGV(":%s HDMI supports DTS HD format", __func__);
1133 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1134 }
1135
1136
1137 // check sample rate caps
1138 i = 0;
1139 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1140 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1141 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1142 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1143 }
1144 }
1145
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001146 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001147}
1148
Alexy Josephb1379942016-01-29 15:49:38 -08001149audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001150 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001151{
1152 struct audio_usecase *usecase;
1153 struct listnode *node;
1154
1155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001157 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001158 ALOGV("%s: usecase id %d", __func__, usecase->id);
1159 return usecase->id;
1160 }
1161 }
1162 return USECASE_INVALID;
1163}
1164
Alexy Josephb1379942016-01-29 15:49:38 -08001165struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001166 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167{
1168 struct audio_usecase *usecase;
1169 struct listnode *node;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->id == uc_id)
1174 return usecase;
1175 }
1176 return NULL;
1177}
1178
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179/*
1180 * is a true native playback active
1181 */
1182bool audio_is_true_native_stream_active(struct audio_device *adev)
1183{
1184 bool active = false;
1185 int i = 0;
1186 struct listnode *node;
1187
1188 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1189 ALOGV("%s:napb: not in true mode or non hdphones device",
1190 __func__);
1191 active = false;
1192 goto exit;
1193 }
1194
1195 list_for_each(node, &adev->usecase_list) {
1196 struct audio_usecase *uc;
1197 uc = node_to_item(node, struct audio_usecase, list);
1198 struct stream_out *curr_out =
1199 (struct stream_out*) uc->stream.out;
1200
1201 if (curr_out && PCM_PLAYBACK == uc->type) {
1202 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1203 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1204 uc->id, curr_out->sample_rate,
1205 curr_out->bit_width,
1206 platform_get_snd_device_name(uc->out_snd_device));
1207
1208 if (is_offload_usecase(uc->id) &&
1209 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1210 active = true;
1211 ALOGD("%s:napb:native stream detected", __func__);
1212 }
1213 }
1214 }
1215exit:
1216 return active;
1217}
1218
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301219/*
1220 * if native DSD playback active
1221 */
1222bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1223{
1224 bool active = false;
1225 struct listnode *node = NULL;
1226 struct audio_usecase *uc = NULL;
1227 struct stream_out *curr_out = NULL;
1228
1229 list_for_each(node, &adev->usecase_list) {
1230 uc = node_to_item(node, struct audio_usecase, list);
1231 curr_out = (struct stream_out*) uc->stream.out;
1232
1233 if (curr_out && PCM_PLAYBACK == uc->type &&
1234 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1235 active = true;
1236 ALOGV("%s:DSD playback is active", __func__);
1237 }
1238 }
1239 return active;
1240}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301241
1242static bool force_device_switch(struct audio_usecase *usecase)
1243{
1244 bool ret = false;
1245 bool is_it_true_mode = false;
1246
1247 if (is_offload_usecase(usecase->id) &&
1248 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001249 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1250 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1251 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301252 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1253 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1254 (!is_it_true_mode && adev->native_playback_enabled)){
1255 ret = true;
1256 ALOGD("napb: time to toggle native mode");
1257 }
1258 }
1259
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301260 // Force all a2dp output devices to reconfigure for proper AFE encode format
1261 if((usecase->stream.out) &&
1262 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1263 audio_extn_a2dp_is_force_device_switch()) {
1264 ALOGD("Force a2dp device switch to update new encoder config");
1265 ret = true;
1266 }
1267
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301268 return ret;
1269}
1270
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001271int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001273 snd_device_t out_snd_device = SND_DEVICE_NONE;
1274 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 struct audio_usecase *usecase = NULL;
1276 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001277 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001278 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001279 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301282 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1283
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase = get_usecase_from_list(adev, uc_id);
1285 if (usecase == NULL) {
1286 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1287 return -EINVAL;
1288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001290 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001291 (usecase->type == VOIP_CALL) ||
1292 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001293 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001294 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001295 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 usecase->devices = usecase->stream.out->devices;
1297 } else {
1298 /*
1299 * If the voice call is active, use the sound devices of voice call usecase
1300 * so that it would not result any device switch. All the usecases will
1301 * be switched to new device when select_devices() is called for voice call
1302 * usecase. This is to avoid switching devices for voice call when
1303 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001304 * choose voice call device only if the use case device is
1305 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001307 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001308 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001309 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001310 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1311 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301312 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1313 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001314 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 in_snd_device = vc_usecase->in_snd_device;
1316 out_snd_device = vc_usecase->out_snd_device;
1317 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001318 } else if (voice_extn_compress_voip_is_active(adev)) {
1319 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001320 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001321 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1322 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001323 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001324 in_snd_device = voip_usecase->in_snd_device;
1325 out_snd_device = voip_usecase->out_snd_device;
1326 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001327 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001328 hfp_ucid = audio_extn_hfp_get_usecase();
1329 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001330 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001331 in_snd_device = hfp_usecase->in_snd_device;
1332 out_snd_device = hfp_usecase->out_snd_device;
1333 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334 }
1335 if (usecase->type == PCM_PLAYBACK) {
1336 usecase->devices = usecase->stream.out->devices;
1337 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001338 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001339 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001340 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001341 if (usecase->stream.out == adev->primary_output &&
1342 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001343 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001344 select_devices(adev, adev->active_input->usecase);
1345 }
1346 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001347 } else if (usecase->type == PCM_CAPTURE) {
1348 usecase->devices = usecase->stream.in->device;
1349 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001350 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001351 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001352 if (adev->active_input &&
1353 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301354 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1355 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1356 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001357 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001358 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001359 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1360 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001361 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001362 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001363 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364 }
1365 }
1366
1367 if (out_snd_device == usecase->out_snd_device &&
1368 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301369
1370 if (!force_device_switch(usecase))
1371 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 }
1373
sangwoobc677242013-08-08 16:53:43 +09001374 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001375 out_snd_device, platform_get_snd_device_name(out_snd_device),
1376 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 /*
1379 * Limitation: While in call, to do a device switch we need to disable
1380 * and enable both RX and TX devices though one of them is same as current
1381 * device.
1382 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001383 if ((usecase->type == VOICE_CALL) &&
1384 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1385 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001386 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001387 }
1388
1389 if (((usecase->type == VOICE_CALL) ||
1390 (usecase->type == VOIP_CALL)) &&
1391 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1392 /* Disable sidetone only if voice/voip call already exists */
1393 if (voice_is_call_state_active(adev) ||
1394 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001395 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001396 }
1397
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398 /* Disable current sound devices */
1399 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 disable_audio_route(adev, usecase);
1401 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 }
1403
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001405 disable_audio_route(adev, usecase);
1406 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 }
1408
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001409 /* Applicable only on the targets that has external modem.
1410 * New device information should be sent to modem before enabling
1411 * the devices to reduce in-call device switch time.
1412 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001413 if ((usecase->type == VOICE_CALL) &&
1414 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1415 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001416 status = platform_switch_voice_call_enable_device_config(adev->platform,
1417 out_snd_device,
1418 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001419 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001420
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 /* Enable new sound devices */
1422 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001423 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001424 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 }
1426
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001427 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301428 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001429 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001430 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431
Avinash Vaish71a8b972014-07-24 15:36:33 +05301432 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001433 status = platform_switch_voice_call_device_post(adev->platform,
1434 out_snd_device,
1435 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301436 enable_audio_route_for_voice_usecases(adev, usecase);
1437 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001438
sangwoo170731f2013-06-08 15:36:36 +09001439 usecase->in_snd_device = in_snd_device;
1440 usecase->out_snd_device = out_snd_device;
1441
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301442 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001443 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301444 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001445 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301446 usecase->stream.out->flags,
1447 usecase->stream.out->format,
1448 usecase->stream.out->sample_rate,
1449 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301450 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301451 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001452 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001453
1454 /* Notify device change info to effect clients registered */
1455 audio_extn_gef_notify_device_config(
1456 usecase->stream.out->devices,
1457 usecase->stream.out->channel_mask,
1458 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301459 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001460
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001461 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001462
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001463 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1464 /* Enable sidetone only if other voice/voip call already exists */
1465 if (voice_is_call_state_active(adev) ||
1466 voice_extn_compress_voip_is_started(adev))
1467 voice_set_sidetone(adev, out_snd_device, true);
1468 }
1469
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001470 /* Applicable only on the targets that has external modem.
1471 * Enable device command should be sent to modem only after
1472 * enabling voice call mixer controls
1473 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001474 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001475 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1476 out_snd_device,
1477 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301478 ALOGD("%s: done",__func__);
1479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 return status;
1481}
1482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483static int stop_input_stream(struct stream_in *in)
1484{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301485 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 struct audio_usecase *uc_info;
1487 struct audio_device *adev = in->dev;
1488
Eric Laurentc8400632013-02-14 19:04:54 -08001489 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Eric Laurent994a6932013-07-17 11:51:42 -07001491 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 uc_info = get_usecase_from_list(adev, in->usecase);
1494 if (uc_info == NULL) {
1495 ALOGE("%s: Could not find the usecase (%d) in the list",
1496 __func__, in->usecase);
1497 return -EINVAL;
1498 }
1499
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001500 /* Close in-call recording streams */
1501 voice_check_and_stop_incall_rec_usecase(adev, in);
1502
Eric Laurent150dbfe2013-02-27 14:31:02 -08001503 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505
1506 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001507 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001509 list_remove(&uc_info->list);
1510 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511
Eric Laurent994a6932013-07-17 11:51:42 -07001512 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 return ret;
1514}
1515
1516int start_input_stream(struct stream_in *in)
1517{
1518 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001519 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520 struct audio_usecase *uc_info;
1521 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301522 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Mingming Yin2664a5b2015-09-03 10:53:11 -07001524 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1525 if (get_usecase_from_list(adev, usecase) == NULL)
1526 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301527 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1528 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001529
Naresh Tanniru80659832014-06-04 18:17:56 +05301530
1531 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301532 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301533 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301534 goto error_config;
1535 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301536
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001537 /* Check if source matches incall recording usecase criteria */
1538 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1539 if (ret)
1540 goto error_config;
1541 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001542 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1543
1544 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1545 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1546 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001547 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001548 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001549
Eric Laurentb23d5282013-05-14 15:27:20 -07001550 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001551 if (in->pcm_device_id < 0) {
1552 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1553 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001554 ret = -EINVAL;
1555 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557
1558 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001560
1561 if (!uc_info) {
1562 ret = -ENOMEM;
1563 goto error_config;
1564 }
1565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 uc_info->id = in->usecase;
1567 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001568 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001569 uc_info->devices = in->device;
1570 uc_info->in_snd_device = SND_DEVICE_NONE;
1571 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001573 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301574 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1575 adev->perf_lock_opts,
1576 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301579 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1580 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001581
1582 unsigned int flags = PCM_IN;
1583 unsigned int pcm_open_retry_count = 0;
1584
1585 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1586 flags |= PCM_MMAP | PCM_NOIRQ;
1587 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001588 } else if (in->realtime) {
1589 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001590 }
1591
1592 while (1) {
1593 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1594 flags, &in->config);
1595 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1596 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1597 if (in->pcm != NULL) {
1598 pcm_close(in->pcm);
1599 in->pcm = NULL;
1600 }
1601 if (pcm_open_retry_count-- == 0) {
1602 ret = -EIO;
1603 goto error_open;
1604 }
1605 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1606 continue;
1607 }
1608 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001610
1611 ALOGV("%s: pcm_prepare", __func__);
1612 ret = pcm_prepare(in->pcm);
1613 if (ret < 0) {
1614 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1615 pcm_close(in->pcm);
1616 in->pcm = NULL;
1617 goto error_open;
1618 }
1619
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001620 register_in_stream(in);
1621 if (in->realtime) {
1622 ret = pcm_start(in->pcm);
1623 if (ret < 0)
1624 goto error_open;
1625 }
1626
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301627 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001628 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001629
Eric Laurentc8400632013-02-14 19:04:54 -08001630 return ret;
1631
1632error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301633 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001635error_config:
1636 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301637 /*
1638 * sleep 50ms to allow sufficient time for kernel
1639 * drivers to recover incases like SSR.
1640 */
1641 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001643
1644 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645}
1646
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001647void lock_input_stream(struct stream_in *in)
1648{
1649 pthread_mutex_lock(&in->pre_lock);
1650 pthread_mutex_lock(&in->lock);
1651 pthread_mutex_unlock(&in->pre_lock);
1652}
1653
1654void lock_output_stream(struct stream_out *out)
1655{
1656 pthread_mutex_lock(&out->pre_lock);
1657 pthread_mutex_lock(&out->lock);
1658 pthread_mutex_unlock(&out->pre_lock);
1659}
1660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001661/* must be called with out->lock locked */
1662static int send_offload_cmd_l(struct stream_out* out, int command)
1663{
1664 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1665
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001666 if (!cmd) {
1667 ALOGE("failed to allocate mem for command 0x%x", command);
1668 return -ENOMEM;
1669 }
1670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 ALOGVV("%s %d", __func__, command);
1672
1673 cmd->cmd = command;
1674 list_add_tail(&out->offload_cmd_list, &cmd->node);
1675 pthread_cond_signal(&out->offload_cond);
1676 return 0;
1677}
1678
1679/* must be called iwth out->lock locked */
1680static void stop_compressed_output_l(struct stream_out *out)
1681{
1682 out->offload_state = OFFLOAD_STATE_IDLE;
1683 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001684 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001685 if (out->compr != NULL) {
1686 compress_stop(out->compr);
1687 while (out->offload_thread_blocked) {
1688 pthread_cond_wait(&out->cond, &out->lock);
1689 }
1690 }
1691}
1692
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001693bool is_offload_usecase(audio_usecase_t uc_id)
1694{
1695 unsigned int i;
1696 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1697 if (uc_id == offload_usecases[i])
1698 return true;
1699 }
1700 return false;
1701}
1702
vivek mehta446c3962015-09-14 10:57:35 -07001703static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001704{
vivek mehta446c3962015-09-14 10:57:35 -07001705 audio_usecase_t ret_uc = USECASE_INVALID;
1706 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001707 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001708 if (!adev->multi_offload_enable) {
1709 if (is_direct_pcm)
1710 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1711 else
1712 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001713
vivek mehta446c3962015-09-14 10:57:35 -07001714 pthread_mutex_lock(&adev->lock);
1715 if (get_usecase_from_list(adev, ret_uc) != NULL)
1716 ret_uc = USECASE_INVALID;
1717 pthread_mutex_unlock(&adev->lock);
1718
1719 return ret_uc;
1720 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721
1722 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001723 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1724 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1725 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1726 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001727 break;
1728 }
1729 }
vivek mehta446c3962015-09-14 10:57:35 -07001730
1731 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1732 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001733}
1734
1735static void free_offload_usecase(struct audio_device *adev,
1736 audio_usecase_t uc_id)
1737{
vivek mehta446c3962015-09-14 10:57:35 -07001738 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001739 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001740
1741 if (!adev->multi_offload_enable)
1742 return;
1743
1744 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1745 if (offload_usecases[offload_uc_index] == uc_id) {
1746 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001747 break;
1748 }
1749 }
1750 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1751}
1752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753static void *offload_thread_loop(void *context)
1754{
1755 struct stream_out *out = (struct stream_out *) context;
1756 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001757 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1760 set_sched_policy(0, SP_FOREGROUND);
1761 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1762
1763 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001764 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 for (;;) {
1766 struct offload_cmd *cmd = NULL;
1767 stream_callback_event_t event;
1768 bool send_callback = false;
1769
1770 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1771 __func__, list_empty(&out->offload_cmd_list),
1772 out->offload_state);
1773 if (list_empty(&out->offload_cmd_list)) {
1774 ALOGV("%s SLEEPING", __func__);
1775 pthread_cond_wait(&out->offload_cond, &out->lock);
1776 ALOGV("%s RUNNING", __func__);
1777 continue;
1778 }
1779
1780 item = list_head(&out->offload_cmd_list);
1781 cmd = node_to_item(item, struct offload_cmd, node);
1782 list_remove(item);
1783
1784 ALOGVV("%s STATE %d CMD %d out->compr %p",
1785 __func__, out->offload_state, cmd->cmd, out->compr);
1786
1787 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1788 free(cmd);
1789 break;
1790 }
1791
1792 if (out->compr == NULL) {
1793 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001794 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 pthread_cond_signal(&out->cond);
1796 continue;
1797 }
1798 out->offload_thread_blocked = true;
1799 pthread_mutex_unlock(&out->lock);
1800 send_callback = false;
1801 switch(cmd->cmd) {
1802 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001803 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001805 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806 send_callback = true;
1807 event = STREAM_CBK_EVENT_WRITE_READY;
1808 break;
1809 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001810 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301811 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001812 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301813 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001814 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301815 if (ret < 0)
1816 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301817 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301818 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001819 compress_drain(out->compr);
1820 else
1821 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301822 if (ret != -ENETRESET) {
1823 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301824 pthread_mutex_lock(&out->lock);
1825 out->send_new_metadata = 1;
1826 out->send_next_track_params = true;
1827 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301828 event = STREAM_CBK_EVENT_DRAIN_READY;
1829 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1830 } else
1831 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832 break;
1833 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001834 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001836 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 send_callback = true;
1838 event = STREAM_CBK_EVENT_DRAIN_READY;
1839 break;
1840 default:
1841 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1842 break;
1843 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001844 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 out->offload_thread_blocked = false;
1846 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001847 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001848 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001849 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001850 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 free(cmd);
1852 }
1853
1854 pthread_cond_signal(&out->cond);
1855 while (!list_empty(&out->offload_cmd_list)) {
1856 item = list_head(&out->offload_cmd_list);
1857 list_remove(item);
1858 free(node_to_item(item, struct offload_cmd, node));
1859 }
1860 pthread_mutex_unlock(&out->lock);
1861
1862 return NULL;
1863}
1864
1865static int create_offload_callback_thread(struct stream_out *out)
1866{
1867 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1868 list_init(&out->offload_cmd_list);
1869 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1870 offload_thread_loop, out);
1871 return 0;
1872}
1873
1874static int destroy_offload_callback_thread(struct stream_out *out)
1875{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001876 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877 stop_compressed_output_l(out);
1878 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1879
1880 pthread_mutex_unlock(&out->lock);
1881 pthread_join(out->offload_thread, (void **) NULL);
1882 pthread_cond_destroy(&out->offload_cond);
1883
1884 return 0;
1885}
1886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887static int stop_output_stream(struct stream_out *out)
1888{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301889 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 struct audio_usecase *uc_info;
1891 struct audio_device *adev = out->dev;
1892
Eric Laurent994a6932013-07-17 11:51:42 -07001893 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 uc_info = get_usecase_from_list(adev, out->usecase);
1896 if (uc_info == NULL) {
1897 ALOGE("%s: Could not find the usecase (%d) in the list",
1898 __func__, out->usecase);
1899 return -EINVAL;
1900 }
1901
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001902 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301903 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001904 if (adev->visualizer_stop_output != NULL)
1905 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001906
1907 audio_extn_dts_remove_state_notifier_node(out->usecase);
1908
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001909 if (adev->offload_effects_stop_output != NULL)
1910 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1911 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001912
Eric Laurent150dbfe2013-02-27 14:31:02 -08001913 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001914 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001915
1916 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001917 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001919 list_remove(&uc_info->list);
1920 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001922 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301923 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001924 ALOGV("Disable passthrough , reset mixer to pcm");
1925 /* NO_PASSTHROUGH */
1926 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001927 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001928 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1929 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001930
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301931 /* Must be called after removing the usecase from list */
1932 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301933 audio_extn_keep_alive_start();
1934
Eric Laurent994a6932013-07-17 11:51:42 -07001935 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 return ret;
1937}
1938
1939int start_output_stream(struct stream_out *out)
1940{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 struct audio_usecase *uc_info;
1943 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301944 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001946 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1947 ret = -EINVAL;
1948 goto error_config;
1949 }
1950
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301951 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1952 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1953 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301954
Naresh Tanniru80659832014-06-04 18:17:56 +05301955 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301956 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301957 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301958 goto error_config;
1959 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301960
Eric Laurentb23d5282013-05-14 15:27:20 -07001961 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 if (out->pcm_device_id < 0) {
1963 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1964 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001965 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001966 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 }
1968
1969 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001970
1971 if (!uc_info) {
1972 ret = -ENOMEM;
1973 goto error_config;
1974 }
1975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 uc_info->id = out->usecase;
1977 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001978 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 uc_info->devices = out->devices;
1980 uc_info->in_snd_device = SND_DEVICE_NONE;
1981 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001982 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301984 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1985 adev->perf_lock_opts,
1986 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301987
1988 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1989 audio_extn_keep_alive_stop();
1990 if (audio_extn_passthru_is_enabled() &&
1991 audio_extn_passthru_is_passthrough_stream(out)) {
1992 audio_extn_passthru_on_start(out);
1993 audio_extn_passthru_update_stream_configuration(adev, out);
1994 }
1995 }
1996
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001997 select_devices(adev, out->usecase);
1998
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001999 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2000 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002001 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002002 unsigned int flags = PCM_OUT;
2003 unsigned int pcm_open_retry_count = 0;
2004 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2005 flags |= PCM_MMAP | PCM_NOIRQ;
2006 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002007 } else if (out->realtime) {
2008 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002009 } else
2010 flags |= PCM_MONOTONIC;
2011
2012 while (1) {
2013 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2014 flags, &out->config);
2015 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2016 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2017 if (out->pcm != NULL) {
2018 pcm_close(out->pcm);
2019 out->pcm = NULL;
2020 }
2021 if (pcm_open_retry_count-- == 0) {
2022 ret = -EIO;
2023 goto error_open;
2024 }
2025 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2026 continue;
2027 }
2028 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002030
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002031 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2032 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002033
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002034 ALOGV("%s: pcm_prepare", __func__);
2035 if (pcm_is_ready(out->pcm)) {
2036 ret = pcm_prepare(out->pcm);
2037 if (ret < 0) {
2038 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2039 pcm_close(out->pcm);
2040 out->pcm = NULL;
2041 goto error_open;
2042 }
2043 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002045 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2046 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002048 out->compr = compress_open(adev->snd_card,
2049 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 COMPRESS_IN, &out->compr_config);
2051 if (out->compr && !is_compress_ready(out->compr)) {
2052 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2053 compress_close(out->compr);
2054 out->compr = NULL;
2055 ret = -EIO;
2056 goto error_open;
2057 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302058 /* compress_open sends params of the track, so reset the flag here */
2059 out->is_compr_metadata_avail = false;
2060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 if (out->offload_callback)
2062 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002063
Fred Oh3f43e742015-03-04 18:42:34 -08002064 /* Since small bufs uses blocking writes, a write will be blocked
2065 for the default max poll time (20s) in the event of an SSR.
2066 Reduce the poll time to observe and deal with SSR faster.
2067 */
Ashish Jain5106d362016-05-11 19:23:33 +05302068 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002069 compress_set_max_poll_wait(out->compr, 1000);
2070 }
2071
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002072 audio_extn_dts_create_state_notifier_node(out->usecase);
2073 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2074 popcount(out->channel_mask),
2075 out->playback_started);
2076
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002077#ifdef DS1_DOLBY_DDP_ENABLED
2078 if (audio_extn_is_dolby_format(out->format))
2079 audio_extn_dolby_send_ddp_endp_params(adev);
2080#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302081 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002082 if (adev->visualizer_start_output != NULL)
2083 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2084 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302085 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002086 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002089
2090 if (ret == 0) {
2091 register_out_stream(out);
2092 if (out->realtime) {
2093 ret = pcm_start(out->pcm);
2094 if (ret < 0)
2095 goto error_open;
2096 }
2097 }
2098
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302099 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002100 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002101
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002102 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302104 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002106error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302107 /*
2108 * sleep 50ms to allow sufficient time for kernel
2109 * drivers to recover incases like SSR.
2110 */
2111 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002112 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115static int check_input_parameters(uint32_t sample_rate,
2116 audio_format_t format,
2117 int channel_count)
2118{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002119 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302121 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2122 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2123 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002124 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302125 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002126
2127 switch (channel_count) {
2128 case 1:
2129 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302130 case 3:
2131 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002132 case 6:
2133 break;
2134 default:
2135 ret = -EINVAL;
2136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137
2138 switch (sample_rate) {
2139 case 8000:
2140 case 11025:
2141 case 12000:
2142 case 16000:
2143 case 22050:
2144 case 24000:
2145 case 32000:
2146 case 44100:
2147 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302148 case 96000:
2149 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150 break;
2151 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002152 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 }
2154
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002155 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156}
2157
2158static size_t get_input_buffer_size(uint32_t sample_rate,
2159 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002160 int channel_count,
2161 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162{
2163 size_t size = 0;
2164
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002165 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2166 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002168 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002169 if (is_low_latency)
2170 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302171
2172 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002174 /* make sure the size is multiple of 32 bytes
2175 * At 48 kHz mono 16-bit PCM:
2176 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2177 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2178 */
2179 size += 0x1f;
2180 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002181
2182 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183}
2184
Ashish Jain5106d362016-05-11 19:23:33 +05302185static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2186{
2187 uint64_t actual_frames_rendered = 0;
2188 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2189
2190 /* This adjustment accounts for buffering after app processor.
2191 * It is based on estimated DSP latency per use case, rather than exact.
2192 */
2193 int64_t platform_latency = platform_render_latency(out->usecase) *
2194 out->sample_rate / 1000000LL;
2195
2196 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2197 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2198 * hence only estimate.
2199 */
2200 int64_t signed_frames = out->written - kernel_buffer_size;
2201
2202 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2203
2204 if (signed_frames > 0)
2205 actual_frames_rendered = signed_frames;
2206
2207 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2208 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2209 (long long int)out->written, (int)kernel_buffer_size,
2210 audio_bytes_per_sample(out->compr_config.codec->format),
2211 popcount(out->channel_mask));
2212
2213 return actual_frames_rendered;
2214}
2215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2217{
2218 struct stream_out *out = (struct stream_out *)stream;
2219
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002220 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221}
2222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002223static int out_set_sample_rate(struct audio_stream *stream __unused,
2224 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225{
2226 return -ENOSYS;
2227}
2228
2229static size_t out_get_buffer_size(const struct audio_stream *stream)
2230{
2231 struct stream_out *out = (struct stream_out *)stream;
2232
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002233 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002235 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2236 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302237 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302238 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002240 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002241 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242}
2243
2244static uint32_t out_get_channels(const struct audio_stream *stream)
2245{
2246 struct stream_out *out = (struct stream_out *)stream;
2247
2248 return out->channel_mask;
2249}
2250
2251static audio_format_t out_get_format(const struct audio_stream *stream)
2252{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253 struct stream_out *out = (struct stream_out *)stream;
2254
2255 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256}
2257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002258static int out_set_format(struct audio_stream *stream __unused,
2259 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260{
2261 return -ENOSYS;
2262}
2263
2264static int out_standby(struct audio_stream *stream)
2265{
2266 struct stream_out *out = (struct stream_out *)stream;
2267 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302269 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2270 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002272 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002274 if (adev->adm_deregister_stream)
2275 adev->adm_deregister_stream(adev->adm_data, out->handle);
2276
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002277 if (is_offload_usecase(out->usecase))
2278 stop_compressed_output_l(out);
2279
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002280 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002282 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2283 voice_extn_compress_voip_close_output_stream(stream);
2284 pthread_mutex_unlock(&adev->lock);
2285 pthread_mutex_unlock(&out->lock);
2286 ALOGD("VOIP output entered standby");
2287 return 0;
2288 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 if (out->pcm) {
2290 pcm_close(out->pcm);
2291 out->pcm = NULL;
2292 }
2293 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002294 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302295 out->send_next_track_params = false;
2296 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002297 out->gapless_mdata.encoder_delay = 0;
2298 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299 if (out->compr != NULL) {
2300 compress_close(out->compr);
2301 out->compr = NULL;
2302 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002303 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002305 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 }
2307 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302308 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 return 0;
2310}
2311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002312static int out_dump(const struct audio_stream *stream __unused,
2313 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314{
2315 return 0;
2316}
2317
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002318static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2319{
2320 int ret = 0;
2321 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002322
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002323 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002324 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002325 return -EINVAL;
2326 }
2327
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302328 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002329
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002330 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2331 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302332 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002333 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002334 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2335 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302336 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002337 }
2338
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002339 ALOGV("%s new encoder delay %u and padding %u", __func__,
2340 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2341
2342 return 0;
2343}
2344
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002345static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2346{
2347 return out == adev->primary_output || out == adev->voice_tx_output;
2348}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2351{
2352 struct stream_out *out = (struct stream_out *)stream;
2353 struct audio_device *adev = out->dev;
2354 struct str_parms *parms;
2355 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002356 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357
sangwoobc677242013-08-08 16:53:43 +09002358 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002359 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302361 if (!parms)
2362 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002363 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2364 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002366 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002367 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002369 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002370 * When HDMI cable is unplugged the music playback is paused and
2371 * the policy manager sends routing=0. But the audioflinger continues
2372 * to write data until standby time (3sec). As the HDMI core is
2373 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002374 * Avoid this by routing audio to speaker until standby.
2375 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002376 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2377 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302378 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002379 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2380 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002381 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302382 /*
2383 * When A2DP is disconnected the
2384 * music playback is paused and the policy manager sends routing=0
2385 * But the audioflingercontinues to write data until standby time
2386 * (3sec). As BT is turned off, the write gets blocked.
2387 * Avoid this by routing audio to speaker until standby.
2388 */
2389 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2390 (val == AUDIO_DEVICE_NONE)) {
2391 val = AUDIO_DEVICE_OUT_SPEAKER;
2392 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002393
2394 /*
2395 * select_devices() call below switches all the usecases on the same
2396 * backend to the new device. Refer to check_usecases_codec_backend() in
2397 * the select_devices(). But how do we undo this?
2398 *
2399 * For example, music playback is active on headset (deep-buffer usecase)
2400 * and if we go to ringtones and select a ringtone, low-latency usecase
2401 * will be started on headset+speaker. As we can't enable headset+speaker
2402 * and headset devices at the same time, select_devices() switches the music
2403 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2404 * So when the ringtone playback is completed, how do we undo the same?
2405 *
2406 * We are relying on the out_set_parameters() call on deep-buffer output,
2407 * once the ringtone playback is ended.
2408 * NOTE: We should not check if the current devices are same as new devices.
2409 * Because select_devices() must be called to switch back the music
2410 * playback to headset.
2411 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002412 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002413 audio_devices_t new_dev = val;
2414 bool same_dev = out->devices == new_dev;
2415 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002416
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002417 if (output_drives_call(adev, out)) {
2418 if(!voice_is_in_call(adev)) {
2419 if (adev->mode == AUDIO_MODE_IN_CALL) {
2420 adev->current_call_output = out;
2421 ret = voice_start_call(adev);
2422 }
2423 } else {
2424 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002425 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002426 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002427 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002428
2429 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002430 if (!same_dev) {
2431 ALOGV("update routing change");
2432 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302433 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2434 adev->perf_lock_opts,
2435 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002436 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002437 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302438 if (!same_dev)
2439 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002440 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002441 }
2442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002444 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002446
2447 if (out == adev->primary_output) {
2448 pthread_mutex_lock(&adev->lock);
2449 audio_extn_set_parameters(adev, parms);
2450 pthread_mutex_unlock(&adev->lock);
2451 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002452 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002453 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002454 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002455
2456 audio_extn_dts_create_state_notifier_node(out->usecase);
2457 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2458 popcount(out->channel_mask),
2459 out->playback_started);
2460
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002461 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002462 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302465error:
Eric Laurent994a6932013-07-17 11:51:42 -07002466 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 return ret;
2468}
2469
2470static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2471{
2472 struct stream_out *out = (struct stream_out *)stream;
2473 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002474 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 char value[256];
2476 struct str_parms *reply = str_parms_create();
2477 size_t i, j;
2478 int ret;
2479 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002480
2481 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002482 if (reply) {
2483 str_parms_destroy(reply);
2484 }
2485 if (query) {
2486 str_parms_destroy(query);
2487 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002488 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2489 return NULL;
2490 }
2491
Eric Laurent994a6932013-07-17 11:51:42 -07002492 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2494 if (ret >= 0) {
2495 value[0] = '\0';
2496 i = 0;
2497 while (out->supported_channel_masks[i] != 0) {
2498 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2499 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2500 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002501 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002503 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 first = false;
2505 break;
2506 }
2507 }
2508 i++;
2509 }
2510 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2511 str = str_parms_to_str(reply);
2512 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002513 voice_extn_out_get_parameters(out, query, reply);
2514 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002515 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002516 free(str);
2517 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002520
Alexy Joseph62142aa2015-11-16 15:10:34 -08002521
2522 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2523 if (ret >= 0) {
2524 value[0] = '\0';
2525 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2526 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302527 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002528 } else {
2529 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302530 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002531 }
2532 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002533 if (str)
2534 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002535 str = str_parms_to_str(reply);
2536 }
2537
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002538 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2539 if (ret >= 0) {
2540 value[0] = '\0';
2541 i = 0;
2542 first = true;
2543 while (out->supported_formats[i] != 0) {
2544 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2545 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2546 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002547 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002548 }
2549 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2550 first = false;
2551 break;
2552 }
2553 }
2554 i++;
2555 }
2556 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002557 if (str)
2558 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002559 str = str_parms_to_str(reply);
2560 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002561
2562 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2563 if (ret >= 0) {
2564 value[0] = '\0';
2565 i = 0;
2566 first = true;
2567 while (out->supported_sample_rates[i] != 0) {
2568 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2569 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2570 if (!first) {
2571 strlcat(value, "|", sizeof(value));
2572 }
2573 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2574 first = false;
2575 break;
2576 }
2577 }
2578 i++;
2579 }
2580 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2581 if (str)
2582 free(str);
2583 str = str_parms_to_str(reply);
2584 }
2585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 str_parms_destroy(query);
2587 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002588 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 return str;
2590}
2591
2592static uint32_t out_get_latency(const struct audio_stream_out *stream)
2593{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002594 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002596 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597
Alexy Josephaa54c872014-12-03 02:46:47 -08002598 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002599 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002600 } else if (out->realtime) {
2601 // since the buffer won't be filled up faster than realtime,
2602 // return a smaller number
2603 if (out->config.rate)
2604 period_ms = (out->af_period_multiplier * out->config.period_size *
2605 1000) / (out->config.rate);
2606 else
2607 period_ms = 0;
2608 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002609 } else {
2610 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002612 }
2613
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302614 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002615 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616}
2617
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302618static float AmpToDb(float amplification)
2619{
2620 if (amplification == 0) {
2621 return DSD_VOLUME_MIN_DB;
2622 }
2623 return 20 * log10(amplification);
2624}
2625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626static int out_set_volume(struct audio_stream_out *stream, float left,
2627 float right)
2628{
Eric Laurenta9024de2013-04-04 09:19:12 -07002629 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002630 int volume[2];
2631
Eric Laurenta9024de2013-04-04 09:19:12 -07002632 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2633 /* only take left channel into account: the API is for stereo anyway */
2634 out->muted = (left == 0.0f);
2635 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002636 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302637 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002638 /*
2639 * Set mute or umute on HDMI passthrough stream.
2640 * Only take left channel into account.
2641 * Mute is 0 and unmute 1
2642 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302643 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302644 } else if (out->format == AUDIO_FORMAT_DSD){
2645 char mixer_ctl_name[128] = "DSD Volume";
2646 struct audio_device *adev = out->dev;
2647 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2648
2649 if (!ctl) {
2650 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2651 __func__, mixer_ctl_name);
2652 return -EINVAL;
2653 }
2654 volume[0] = (int)(AmpToDb(left));
2655 volume[1] = (int)(AmpToDb(right));
2656 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2657 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002658 } else {
2659 char mixer_ctl_name[128];
2660 struct audio_device *adev = out->dev;
2661 struct mixer_ctl *ctl;
2662 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002663 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002665 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2666 "Compress Playback %d Volume", pcm_device_id);
2667 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2668 if (!ctl) {
2669 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2670 __func__, mixer_ctl_name);
2671 return -EINVAL;
2672 }
2673 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2674 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2675 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2676 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002678 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 return -ENOSYS;
2681}
2682
2683static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2684 size_t bytes)
2685{
2686 struct stream_out *out = (struct stream_out *)stream;
2687 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302688 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002689 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002691 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302692
Naresh Tanniru80659832014-06-04 18:17:56 +05302693 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002694
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302695 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302696 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302697 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2698 pthread_mutex_unlock(&out->lock);
2699 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302700 } else {
2701 /* increase written size during SSR to avoid mismatch
2702 * with the written frames count in AF
2703 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002704 // bytes per frame
2705 size_t bpf = audio_bytes_per_sample(out->format) *
2706 audio_channel_count_from_out_mask(out->channel_mask);
2707 if (bpf != 0)
2708 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302709 ALOGD(" %s: sound card is not active/SSR state", __func__);
2710 ret= -EIO;
2711 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302712 }
2713 }
2714
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302715 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302716 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2717 if (audio_bytes_per_sample(out->format) != 0)
2718 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2719 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302720 goto exit;
2721 }
2722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002724 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002725 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002726 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2727 ret = voice_extn_compress_voip_start_output_stream(out);
2728 else
2729 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002730 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002733 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 goto exit;
2735 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002736
2737 if (last_known_cal_step != -1) {
2738 ALOGD("%s: retry previous failed cal level set", __func__);
2739 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2740 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742
Ashish Jain81eb2a82015-05-13 10:52:34 +05302743 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002744 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302745 adev->is_channel_status_set = true;
2746 }
2747
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002748 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002749 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002750 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002751 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002752 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2753 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302754 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2755 ALOGD("copl(%p):send next track params in gapless", out);
2756 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2757 out->send_next_track_params = false;
2758 out->is_compr_metadata_avail = false;
2759 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002760 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302761 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302762 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002763
Ashish Jain83a6cc22016-06-28 14:34:17 +05302764 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302765 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302766 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302767 pthread_mutex_unlock(&out->lock);
2768 return -EINVAL;
2769 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302770 audio_format_t dst_format = out->hal_op_format;
2771 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302772
2773 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2774 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2775
Ashish Jain83a6cc22016-06-28 14:34:17 +05302776 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302777 dst_format,
2778 buffer,
2779 src_format,
2780 frames);
2781
Ashish Jain83a6cc22016-06-28 14:34:17 +05302782 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302783 bytes_to_write);
2784
2785 /*Convert written bytes in audio flinger format*/
2786 if (ret > 0)
2787 ret = ((ret * format_to_bitwidth_table[out->format]) /
2788 format_to_bitwidth_table[dst_format]);
2789 }
2790 } else
2791 ret = compress_write(out->compr, buffer, bytes);
2792
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302793 if (ret < 0)
2794 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302795 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302796 /*msg to cb thread only if non blocking write is enabled*/
2797 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302798 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302800 } else if (-ENETRESET == ret) {
2801 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2802 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2803 pthread_mutex_unlock(&out->lock);
2804 out_standby(&out->stream.common);
2805 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 }
Ashish Jain5106d362016-05-11 19:23:33 +05302807 if ( ret == (ssize_t)bytes && !out->non_blocking)
2808 out->written += bytes;
2809
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302810 /* Call compr start only when non-zero bytes of data is there to be rendered */
2811 if (!out->playback_started && ret > 0) {
2812 int status = compress_start(out->compr);
2813 if (status < 0) {
2814 ret = status;
2815 ALOGE("%s: compr start failed with err %d", __func__, errno);
2816 goto exit;
2817 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002818 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819 out->playback_started = 1;
2820 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002821
2822 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2823 popcount(out->channel_mask),
2824 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 }
2826 pthread_mutex_unlock(&out->lock);
2827 return ret;
2828 } else {
2829 if (out->pcm) {
2830 if (out->muted)
2831 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002832
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302833 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002834
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002835 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002836
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002837 if (out->config.rate)
2838 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2839 out->config.rate;
2840
2841 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2842
2843 request_out_focus(out, ns);
2844
2845 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002846 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002847 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302848 out->convert_buffer != NULL) {
2849
2850 memcpy_by_audio_format(out->convert_buffer,
2851 out->hal_op_format,
2852 buffer,
2853 out->hal_ip_format,
2854 out->config.period_size * out->config.channels);
2855
2856 ret = pcm_write(out->pcm, out->convert_buffer,
2857 (out->config.period_size *
2858 out->config.channels *
2859 format_to_bitwidth_table[out->hal_op_format]));
2860 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002861 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302862 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002863
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002864 release_out_focus(out);
2865
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302866 if (ret < 0)
2867 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302868 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2869 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2870 else
2871 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 }
2874
2875exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302876 /* ToDo: There may be a corner case when SSR happens back to back during
2877 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302878 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302879 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302880 }
2881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 pthread_mutex_unlock(&out->lock);
2883
2884 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002885 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002886 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302887 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302888 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302889 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302890 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302891 out->standby = true;
2892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302894 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2895 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2896 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 }
2898 return bytes;
2899}
2900
2901static int out_get_render_position(const struct audio_stream_out *stream,
2902 uint32_t *dsp_frames)
2903{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302905 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002906
2907 if (dsp_frames == NULL)
2908 return -EINVAL;
2909
2910 *dsp_frames = 0;
2911 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002912 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302913
2914 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2915 * this operation and adev_close_output_stream(where out gets reset).
2916 */
2917 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2918 *dsp_frames = get_actual_pcm_frames_rendered(out);
2919 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2920 return 0;
2921 }
2922
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002923 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302924 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302925 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302927 if (ret < 0)
2928 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302930 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931 }
2932 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302933 if (-ENETRESET == ret) {
2934 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2935 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2936 return -EINVAL;
2937 } else if(ret < 0) {
2938 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2939 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302940 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2941 /*
2942 * Handle corner case where compress session is closed during SSR
2943 * and timestamp is queried
2944 */
2945 ALOGE(" ERROR: sound card not active, return error");
2946 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302947 } else {
2948 return 0;
2949 }
Zhou Song32a556e2015-05-05 10:46:56 +08002950 } else if (audio_is_linear_pcm(out->format)) {
2951 *dsp_frames = out->written;
2952 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 } else
2954 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955}
2956
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002957static int out_add_audio_effect(const struct audio_stream *stream __unused,
2958 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959{
2960 return 0;
2961}
2962
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002963static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2964 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965{
2966 return 0;
2967}
2968
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002969static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2970 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971{
2972 return -EINVAL;
2973}
2974
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002975static int out_get_presentation_position(const struct audio_stream_out *stream,
2976 uint64_t *frames, struct timespec *timestamp)
2977{
2978 struct stream_out *out = (struct stream_out *)stream;
2979 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002980 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002981
Ashish Jain5106d362016-05-11 19:23:33 +05302982 /* below piece of code is not guarded against any lock because audioFliner serializes
2983 * this operation and adev_close_output_stream( where out gets reset).
2984 */
2985 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2986 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2987 *frames = get_actual_pcm_frames_rendered(out);
2988 /* this is the best we can do */
2989 clock_gettime(CLOCK_MONOTONIC, timestamp);
2990 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2991 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2992 return 0;
2993 }
2994
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002995 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002996
Ashish Jain5106d362016-05-11 19:23:33 +05302997 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2998 ret = compress_get_tstamp(out->compr, &dsp_frames,
2999 &out->sample_rate);
3000 ALOGVV("%s rendered frames %ld sample_rate %d",
3001 __func__, dsp_frames, out->sample_rate);
3002 *frames = dsp_frames;
3003 if (ret < 0)
3004 ret = -errno;
3005 if (-ENETRESET == ret) {
3006 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3007 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3008 ret = -EINVAL;
3009 } else
3010 ret = 0;
3011 /* this is the best we can do */
3012 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003013 } else {
3014 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003015 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003016 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3017 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003018 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003019 // This adjustment accounts for buffering after app processor.
3020 // It is based on estimated DSP latency per use case, rather than exact.
3021 signed_frames -=
3022 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3023
Eric Laurent949a0892013-09-20 09:20:13 -07003024 // It would be unusual for this value to be negative, but check just in case ...
3025 if (signed_frames >= 0) {
3026 *frames = signed_frames;
3027 ret = 0;
3028 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003029 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303030 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3031 *frames = out->written;
3032 clock_gettime(CLOCK_MONOTONIC, timestamp);
3033 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003034 }
3035 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003036 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003037 return ret;
3038}
3039
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040static int out_set_callback(struct audio_stream_out *stream,
3041 stream_callback_t callback, void *cookie)
3042{
3043 struct stream_out *out = (struct stream_out *)stream;
3044
3045 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003046 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 out->offload_callback = callback;
3048 out->offload_cookie = cookie;
3049 pthread_mutex_unlock(&out->lock);
3050 return 0;
3051}
3052
3053static int out_pause(struct audio_stream_out* stream)
3054{
3055 struct stream_out *out = (struct stream_out *)stream;
3056 int status = -ENOSYS;
3057 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003058 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003059 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003060 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303062 struct audio_device *adev = out->dev;
3063 int snd_scard_state = get_snd_card_state(adev);
3064
3065 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3066 status = compress_pause(out->compr);
3067
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003069
Mingming Yin21854652016-04-13 11:54:02 -07003070 if (audio_extn_passthru_is_active()) {
3071 ALOGV("offload use case, pause passthru");
3072 audio_extn_passthru_on_pause(out);
3073 }
3074
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303075 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003076 audio_extn_dts_notify_playback_state(out->usecase, 0,
3077 out->sample_rate, popcount(out->channel_mask),
3078 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 }
3080 pthread_mutex_unlock(&out->lock);
3081 }
3082 return status;
3083}
3084
3085static int out_resume(struct audio_stream_out* stream)
3086{
3087 struct stream_out *out = (struct stream_out *)stream;
3088 int status = -ENOSYS;
3089 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003090 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003091 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003093 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303095 struct audio_device *adev = out->dev;
3096 int snd_scard_state = get_snd_card_state(adev);
3097
Mingming Yin21854652016-04-13 11:54:02 -07003098 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3099 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3100 pthread_mutex_lock(&out->dev->lock);
3101 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003102 pthread_mutex_unlock(&out->dev->lock);
3103 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303104 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003105 }
3106 if (!status) {
3107 out->offload_state = OFFLOAD_STATE_PLAYING;
3108 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303109 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003110 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3111 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 }
3113 pthread_mutex_unlock(&out->lock);
3114 }
3115 return status;
3116}
3117
3118static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3119{
3120 struct stream_out *out = (struct stream_out *)stream;
3121 int status = -ENOSYS;
3122 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003123 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003124 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003125 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3126 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3127 else
3128 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3129 pthread_mutex_unlock(&out->lock);
3130 }
3131 return status;
3132}
3133
3134static int out_flush(struct audio_stream_out* stream)
3135{
3136 struct stream_out *out = (struct stream_out *)stream;
3137 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003138 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003139 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003140 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003141 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3142 stop_compressed_output_l(out);
3143 out->written = 0;
3144 } else {
3145 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3146 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003148 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 return 0;
3150 }
3151 return -ENOSYS;
3152}
3153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154/** audio_stream_in implementation **/
3155static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3156{
3157 struct stream_in *in = (struct stream_in *)stream;
3158
3159 return in->config.rate;
3160}
3161
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003162static int in_set_sample_rate(struct audio_stream *stream __unused,
3163 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164{
3165 return -ENOSYS;
3166}
3167
3168static size_t in_get_buffer_size(const struct audio_stream *stream)
3169{
3170 struct stream_in *in = (struct stream_in *)stream;
3171
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003172 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3173 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003174 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3175 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003176
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003177 return in->config.period_size * in->af_period_multiplier *
3178 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179}
3180
3181static uint32_t in_get_channels(const struct audio_stream *stream)
3182{
3183 struct stream_in *in = (struct stream_in *)stream;
3184
3185 return in->channel_mask;
3186}
3187
3188static audio_format_t in_get_format(const struct audio_stream *stream)
3189{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003190 struct stream_in *in = (struct stream_in *)stream;
3191
3192 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193}
3194
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003195static int in_set_format(struct audio_stream *stream __unused,
3196 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197{
3198 return -ENOSYS;
3199}
3200
3201static int in_standby(struct audio_stream *stream)
3202{
3203 struct stream_in *in = (struct stream_in *)stream;
3204 struct audio_device *adev = in->dev;
3205 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303206 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3207 stream, in->usecase, use_case_table[in->usecase]);
3208
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003209 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003210 if (!in->standby && in->is_st_session) {
3211 ALOGD("%s: sound trigger pcm stop lab", __func__);
3212 audio_extn_sound_trigger_stop_lab(in);
3213 in->standby = 1;
3214 }
3215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003217 if (adev->adm_deregister_stream)
3218 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3219
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003220 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003222 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3223 voice_extn_compress_voip_close_input_stream(stream);
3224 ALOGD("VOIP input entered standby");
3225 } else {
3226 if (in->pcm) {
3227 pcm_close(in->pcm);
3228 in->pcm = NULL;
3229 }
3230 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003231 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003232 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 }
3234 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003235 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 return status;
3237}
3238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003239static int in_dump(const struct audio_stream *stream __unused,
3240 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241{
3242 return 0;
3243}
3244
3245static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3246{
3247 struct stream_in *in = (struct stream_in *)stream;
3248 struct audio_device *adev = in->dev;
3249 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003251 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303253 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 parms = str_parms_create_str(kvpairs);
3255
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303256 if (!parms)
3257 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003258 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003259 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003260
3261 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3262 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 val = atoi(value);
3264 /* no audio source uses val == 0 */
3265 if ((in->source != val) && (val != 0)) {
3266 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003267 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3268 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3269 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003270 (in->config.rate == 8000 || in->config.rate == 16000 ||
3271 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003272 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003273 err = voice_extn_compress_voip_open_input_stream(in);
3274 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003275 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003276 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003277 }
3278 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 }
3280 }
3281
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003282 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3283 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003285 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 in->device = val;
3287 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003288 if (!in->standby && !in->is_st_session) {
3289 ALOGV("update input routing change");
3290 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003291 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 }
3294 }
3295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003297 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298
3299 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303300error:
Eric Laurent994a6932013-07-17 11:51:42 -07003301 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 return ret;
3303}
3304
3305static char* in_get_parameters(const struct audio_stream *stream,
3306 const char *keys)
3307{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003308 struct stream_in *in = (struct stream_in *)stream;
3309 struct str_parms *query = str_parms_create_str(keys);
3310 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003311 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003312
3313 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003314 if (reply) {
3315 str_parms_destroy(reply);
3316 }
3317 if (query) {
3318 str_parms_destroy(query);
3319 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003320 ALOGE("in_get_parameters: failed to create query or reply");
3321 return NULL;
3322 }
3323
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003324 ALOGV("%s: enter: keys - %s", __func__, keys);
3325
3326 voice_extn_in_get_parameters(in, query, reply);
3327
3328 str = str_parms_to_str(reply);
3329 str_parms_destroy(query);
3330 str_parms_destroy(reply);
3331
3332 ALOGV("%s: exit: returns - %s", __func__, str);
3333 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static int in_set_gain(struct audio_stream_in *stream __unused,
3337 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338{
3339 return 0;
3340}
3341
3342static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3343 size_t bytes)
3344{
3345 struct stream_in *in = (struct stream_in *)stream;
3346 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303347 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303348 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303349 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003351 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303352
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003353 if (in->is_st_session) {
3354 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3355 /* Read from sound trigger HAL */
3356 audio_extn_sound_trigger_read(in, buffer, bytes);
3357 pthread_mutex_unlock(&in->lock);
3358 return bytes;
3359 }
3360
Ashish Jainbbce4322016-02-16 13:25:27 +05303361 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003362 ALOGD(" %s: sound card is not active/SSR state", __func__);
3363 ret= -EIO;;
3364 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303365 }
3366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003368 pthread_mutex_lock(&adev->lock);
3369 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3370 ret = voice_extn_compress_voip_start_input_stream(in);
3371 else
3372 ret = start_input_stream(in);
3373 pthread_mutex_unlock(&adev->lock);
3374 if (ret != 0) {
3375 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 }
3377 in->standby = 0;
3378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003380 // what's the duration requested by the client?
3381 long ns = 0;
3382
3383 if (in->config.rate)
3384 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3385 in->config.rate;
3386
3387 request_in_focus(in, ns);
3388 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303391 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003392 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303393 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003394 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003395 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003396 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303397 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003398 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303399 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3400 if (bytes % 4 == 0) {
3401 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3402 int_buf_stream = buffer;
3403 for (size_t itt=0; itt < bytes/4 ; itt++) {
3404 int_buf_stream[itt] >>= 8;
3405 }
3406 } else {
3407 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3408 ret = -EINVAL;
3409 goto exit;
3410 }
3411 } if (ret < 0) {
3412 ret = -errno;
3413 }
3414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 }
3416
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003417 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 /*
3420 * Instead of writing zeroes here, we could trust the hardware
3421 * to always provide zeroes when muted.
3422 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303423 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3424 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 memset(buffer, 0, bytes);
3426
3427exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303428 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303429 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003430 if (-ENETRESET == ret)
3431 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 pthread_mutex_unlock(&in->lock);
3434
3435 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303436 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303437 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303438 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303439 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303440 in->standby = true;
3441 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303442 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003444 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303445 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303446 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 }
3448 return bytes;
3449}
3450
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003451static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452{
3453 return 0;
3454}
3455
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003456static int add_remove_audio_effect(const struct audio_stream *stream,
3457 effect_handle_t effect,
3458 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003460 struct stream_in *in = (struct stream_in *)stream;
3461 int status = 0;
3462 effect_descriptor_t desc;
3463
3464 status = (*effect)->get_descriptor(effect, &desc);
3465 if (status != 0)
3466 return status;
3467
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003468 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003469 pthread_mutex_lock(&in->dev->lock);
3470 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3471 in->enable_aec != enable &&
3472 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3473 in->enable_aec = enable;
3474 if (!in->standby)
3475 select_devices(in->dev, in->usecase);
3476 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003477 if (in->enable_ns != enable &&
3478 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3479 in->enable_ns = enable;
3480 if (!in->standby)
3481 select_devices(in->dev, in->usecase);
3482 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003483 pthread_mutex_unlock(&in->dev->lock);
3484 pthread_mutex_unlock(&in->lock);
3485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 return 0;
3487}
3488
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003489static int in_add_audio_effect(const struct audio_stream *stream,
3490 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
Eric Laurent994a6932013-07-17 11:51:42 -07003492 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493 return add_remove_audio_effect(stream, effect, true);
3494}
3495
3496static int in_remove_audio_effect(const struct audio_stream *stream,
3497 effect_handle_t effect)
3498{
Eric Laurent994a6932013-07-17 11:51:42 -07003499 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003500 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501}
3502
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303503int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 audio_io_handle_t handle,
3505 audio_devices_t devices,
3506 audio_output_flags_t flags,
3507 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003508 struct audio_stream_out **stream_out,
3509 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 struct audio_device *adev = (struct audio_device *)dev;
3512 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303513 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003514 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303517
3518 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3519 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003520 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303521 return -EINVAL;
3522 }
3523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3525
Mingming Yin3a941d42016-02-17 18:08:05 -08003526 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3527 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303528 devices, flags, &out->stream);
3529
3530
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003531 if (!out) {
3532 return -ENOMEM;
3533 }
3534
Haynes Mathew George204045b2015-02-25 20:32:03 -08003535 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003536 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003537 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 if (devices == AUDIO_DEVICE_NONE)
3540 devices = AUDIO_DEVICE_OUT_SPEAKER;
3541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 out->flags = flags;
3543 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003544 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003545 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003546 out->sample_rate = config->sample_rate;
3547 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3548 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003549 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003550 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003551 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303552 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Mingming Yin3a941d42016-02-17 18:08:05 -08003554 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3555 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3556 pthread_mutex_lock(&adev->lock);
3557 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3558 ret = read_hdmi_sink_caps(out);
3559 pthread_mutex_unlock(&adev->lock);
3560 if (ret != 0) {
3561 if (ret == -ENOSYS) {
3562 /* ignore and go with default */
3563 ret = 0;
3564 } else {
3565 ALOGE("error reading hdmi sink caps");
3566 goto error_open;
3567 }
3568 }
3569 }
3570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003572 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303573 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3574 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003575 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3576 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3577
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003578 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003579 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3580 /*
3581 * Do not handle stereo output in Multi-channel cases
3582 * Stereo case is handled in normal playback path
3583 */
3584 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3585 ret = AUDIO_CHANNEL_OUT_STEREO;
3586 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003587
3588 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3589 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003590 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003591 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003592 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003593
3594 if (config->sample_rate == 0)
3595 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3596 if (config->channel_mask == 0)
3597 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003598 if (config->format == 0)
3599 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003600
3601 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003602 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003603 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3605 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003607 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003609 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3610 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003611 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003612 ret = voice_extn_compress_voip_open_output_stream(out);
3613 if (ret != 0) {
3614 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3615 __func__, ret);
3616 goto error_open;
3617 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003618 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3619 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3620
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3622 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3623 ALOGE("%s: Unsupported Offload information", __func__);
3624 ret = -EINVAL;
3625 goto error_open;
3626 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003627
Mingming Yin3a941d42016-02-17 18:08:05 -08003628 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003629 if(config->offload_info.format == 0)
3630 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003631 if (config->offload_info.sample_rate == 0)
3632 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003633 }
3634
Mingming Yin90310102013-11-13 16:57:00 -08003635 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303636 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003637 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003638 ret = -EINVAL;
3639 goto error_open;
3640 }
3641
3642 out->compr_config.codec = (struct snd_codec *)
3643 calloc(1, sizeof(struct snd_codec));
3644
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003645 if (!out->compr_config.codec) {
3646 ret = -ENOMEM;
3647 goto error_open;
3648 }
3649
vivek mehta0ea887a2015-08-26 14:01:20 -07003650 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303651 out->stream.pause = out_pause;
3652 out->stream.flush = out_flush;
3653 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003654 out->usecase = get_offload_usecase(adev, true);
3655 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003656 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003657 out->stream.set_callback = out_set_callback;
3658 out->stream.pause = out_pause;
3659 out->stream.resume = out_resume;
3660 out->stream.drain = out_drain;
3661 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003662 out->usecase = get_offload_usecase(adev, false);
3663 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003664 }
vivek mehta446c3962015-09-14 10:57:35 -07003665
3666 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003667 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3668 config->format == 0 && config->sample_rate == 0 &&
3669 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003670 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003671 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3672 } else {
3673 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3674 ret = -EEXIST;
3675 goto error_open;
3676 }
vivek mehta446c3962015-09-14 10:57:35 -07003677 }
3678
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 if (config->offload_info.channel_mask)
3680 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003681 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003683 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003684 } else {
3685 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3686 ret = -EINVAL;
3687 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003688 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003689
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003690 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 out->sample_rate = config->offload_info.sample_rate;
3692
Mingming Yin3ee55c62014-08-04 14:23:35 -07003693 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003694
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303695 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3696 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3697 audio_extn_dolby_send_ddp_endp_params(adev);
3698 audio_extn_dolby_set_dmid(adev);
3699 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003700
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003701 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003702 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 out->compr_config.codec->bit_rate =
3704 config->offload_info.bit_rate;
3705 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303706 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003707 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303708 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003709 /*TODO: Do we need to change it for passthrough */
3710 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003711
Manish Dewangana6fc5442015-08-24 20:30:31 +05303712 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3713 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3714 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3715 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303716
3717 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3718 AUDIO_FORMAT_PCM) {
3719
3720 /*Based on platform support, configure appropriate alsa format for corresponding
3721 *hal input format.
3722 */
3723 out->compr_config.codec->format = hal_format_to_alsa(
3724 config->offload_info.format);
3725
Ashish Jain83a6cc22016-06-28 14:34:17 +05303726 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303727 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303728 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303729
3730 /*for direct PCM playback populate bit_width based on selected alsa format as
3731 *hal input format and alsa format might differ based on platform support.
3732 */
3733 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303734 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303735
3736 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3737
3738 /* Check if alsa session is configured with the same format as HAL input format,
3739 * if not then derive correct fragment size needed to accomodate the
3740 * conversion of HAL input format to alsa format.
3741 */
3742 audio_extn_utils_update_direct_pcm_fragment_size(out);
3743
3744 /*if hal input and output fragment size is different this indicates HAL input format is
3745 *not same as the alsa format
3746 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303747 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303748 /*Allocate a buffer to convert input data to the alsa configured format.
3749 *size of convert buffer is equal to the size required to hold one fragment size
3750 *worth of pcm data, this is because flinger does not write more than fragment_size
3751 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303752 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3753 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303754 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3755 ret = -ENOMEM;
3756 goto error_open;
3757 }
3758 }
3759 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3760 out->compr_config.fragment_size =
3761 audio_extn_passthru_get_buffer_size(&config->offload_info);
3762 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3763 } else {
3764 out->compr_config.fragment_size =
3765 platform_get_compress_offload_buffer_size(&config->offload_info);
3766 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3767 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003768
Amit Shekhar6f461b12014-08-01 14:52:58 -07003769 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303770 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003771
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3773 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003774
Alexy Josephaa54c872014-12-03 02:46:47 -08003775
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003776 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303777 out->send_next_track_params = false;
3778 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003779 out->offload_state = OFFLOAD_STATE_IDLE;
3780 out->playback_started = 0;
3781
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003782 audio_extn_dts_create_state_notifier_node(out->usecase);
3783
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003784 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3785 __func__, config->offload_info.version,
3786 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303787
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303788 /*Check if DSD audio format is supported in codec
3789 *and there is no active native DSD use case
3790 */
3791
3792 if ((config->format == AUDIO_FORMAT_DSD) &&
3793 (!platform_check_codec_dsd_support(adev->platform) ||
3794 audio_is_dsd_native_stream_active(adev))) {
3795 ret = -EINVAL;
3796 goto error_open;
3797 }
3798
Ashish Jain5106d362016-05-11 19:23:33 +05303799 /* Disable gapless if any of the following is true
3800 * passthrough playback
3801 * AV playback
3802 * Direct PCM playback
3803 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303804 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303805 (config->format == AUDIO_FORMAT_DSD) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303806 config->offload_info.has_video ||
3807 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3808 check_and_set_gapless_mode(adev, false);
3809 } else
3810 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003811
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303812 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003813 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3814 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303815 if (config->format == AUDIO_FORMAT_DSD) {
3816 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3817 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3818 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003819
3820 create_offload_callback_thread(out);
3821
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003822 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303823 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003824 if (ret != 0) {
3825 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3826 __func__, ret);
3827 goto error_open;
3828 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003829 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3830 if (config->sample_rate == 0)
3831 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3832 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3833 config->sample_rate != 8000) {
3834 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3835 ret = -EINVAL;
3836 goto error_open;
3837 }
3838 out->sample_rate = config->sample_rate;
3839 out->config.rate = config->sample_rate;
3840 if (config->format == AUDIO_FORMAT_DEFAULT)
3841 config->format = AUDIO_FORMAT_PCM_16_BIT;
3842 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3843 config->format = AUDIO_FORMAT_PCM_16_BIT;
3844 ret = -EINVAL;
3845 goto error_open;
3846 }
3847 out->format = config->format;
3848 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3849 out->config = pcm_config_afe_proxy_playback;
3850 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003851 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303852 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3853 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003854 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3855 out->flags);
3856 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303857 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3858 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3859 out->config = pcm_config_low_latency;
3860 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3861 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3862 out->config = pcm_config_deep_buffer;
3863 } else {
3864 /* primary path is the default path selected if no other outputs are available/suitable */
3865 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3866 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3867 }
3868 out->hal_ip_format = format = out->format;
3869 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3870 out->hal_op_format = pcm_format_to_hal(out->config.format);
3871 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3872 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003873 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303874 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3875 if (out->hal_ip_format != out->hal_op_format) {
3876 uint32_t buffer_size = out->config.period_size *
3877 format_to_bitwidth_table[out->hal_op_format] *
3878 out->config.channels;
3879 out->convert_buffer = calloc(1, buffer_size);
3880 if (out->convert_buffer == NULL){
3881 ALOGE("Allocation failed for convert buffer for size %d",
3882 out->compr_config.fragment_size);
3883 ret = -ENOMEM;
3884 goto error_open;
3885 }
3886 ALOGD("Convert buffer allocated of size %d", buffer_size);
3887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 }
3889
Ashish Jain83a6cc22016-06-28 14:34:17 +05303890 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3891 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3892
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 /* TODO remove this hardcoding and check why width is zero*/
3894 if (out->bit_width == 0)
3895 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003896 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3897 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003898 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303899 out->bit_width, out->channel_mask,
3900 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003901 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3902 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3903 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003904 if(adev->primary_output == NULL)
3905 adev->primary_output = out;
3906 else {
3907 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003908 ret = -EEXIST;
3909 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003910 }
3911 }
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 /* Check if this usecase is already existing */
3914 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003915 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3916 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003919 ret = -EEXIST;
3920 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 }
3922 pthread_mutex_unlock(&adev->lock);
3923
3924 out->stream.common.get_sample_rate = out_get_sample_rate;
3925 out->stream.common.set_sample_rate = out_set_sample_rate;
3926 out->stream.common.get_buffer_size = out_get_buffer_size;
3927 out->stream.common.get_channels = out_get_channels;
3928 out->stream.common.get_format = out_get_format;
3929 out->stream.common.set_format = out_set_format;
3930 out->stream.common.standby = out_standby;
3931 out->stream.common.dump = out_dump;
3932 out->stream.common.set_parameters = out_set_parameters;
3933 out->stream.common.get_parameters = out_get_parameters;
3934 out->stream.common.add_audio_effect = out_add_audio_effect;
3935 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3936 out->stream.get_latency = out_get_latency;
3937 out->stream.set_volume = out_set_volume;
3938 out->stream.write = out_write;
3939 out->stream.get_render_position = out_get_render_position;
3940 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003941 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003943 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003945 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003946 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947
3948 config->format = out->stream.common.get_format(&out->stream.common);
3949 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3950 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3951
3952 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303953 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003954 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003955
3956 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3957 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3958 popcount(out->channel_mask), out->playback_started);
3959
Eric Laurent994a6932013-07-17 11:51:42 -07003960 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003962
3963error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303964 if (out->convert_buffer)
3965 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003966 free(out);
3967 *stream_out = NULL;
3968 ALOGD("%s: exit: ret %d", __func__, ret);
3969 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970}
3971
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303972void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 struct audio_stream_out *stream)
3974{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 struct stream_out *out = (struct stream_out *)stream;
3976 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003977 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303979 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3980
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003981 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303982 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003983 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303984 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003985 if(ret != 0)
3986 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3987 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003988 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003989 out_standby(&stream->common);
3990
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003991 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003992 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003994 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 if (out->compr_config.codec != NULL)
3996 free(out->compr_config.codec);
3997 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003998
Ashish Jain83a6cc22016-06-28 14:34:17 +05303999 if (out->convert_buffer != NULL) {
4000 free(out->convert_buffer);
4001 out->convert_buffer = NULL;
4002 }
4003
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004004 if (adev->voice_tx_output == out)
4005 adev->voice_tx_output = NULL;
4006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004007 pthread_cond_destroy(&out->cond);
4008 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004010 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011}
4012
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004013static void close_compress_sessions(struct audio_device *adev)
4014{
Mingming Yin7b762e72015-03-04 13:47:32 -08004015 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304016 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004017 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004018 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304019
4020 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004021 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304022 if (is_offload_usecase(usecase->id)) {
4023 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004024 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4025 out = usecase->stream.out;
4026 pthread_mutex_unlock(&adev->lock);
4027 out_standby(&out->stream.common);
4028 pthread_mutex_lock(&adev->lock);
4029 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304030 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004031 }
4032 pthread_mutex_unlock(&adev->lock);
4033}
4034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4036{
4037 struct audio_device *adev = (struct audio_device *)dev;
4038 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004040 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004041 int ret;
4042 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004044 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304047 if (!parms)
4048 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004049 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4050 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304051 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304052 if (strstr(snd_card_status, "OFFLINE")) {
4053 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304054 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004055 //close compress sessions on OFFLINE status
4056 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304057 } else if (strstr(snd_card_status, "ONLINE")) {
4058 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304059 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004060 //send dts hpx license if enabled
4061 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304062 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304063 }
4064
4065 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004066 status = voice_set_parameters(adev, parms);
4067 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004068 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004070 status = platform_set_parameters(adev->platform, parms);
4071 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004072 goto done;
4073
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004074 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4075 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004076 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4078 adev->bluetooth_nrec = true;
4079 else
4080 adev->bluetooth_nrec = false;
4081 }
4082
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004083 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4084 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4086 adev->screen_off = false;
4087 else
4088 adev->screen_off = true;
4089 }
4090
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004091 ret = str_parms_get_int(parms, "rotation", &val);
4092 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004093 bool reverse_speakers = false;
4094 switch(val) {
4095 // FIXME: note that the code below assumes that the speakers are in the correct placement
4096 // relative to the user when the device is rotated 90deg from its default rotation. This
4097 // assumption is device-specific, not platform-specific like this code.
4098 case 270:
4099 reverse_speakers = true;
4100 break;
4101 case 0:
4102 case 90:
4103 case 180:
4104 break;
4105 default:
4106 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004107 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004108 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004109 if (status == 0) {
4110 if (adev->speaker_lr_swap != reverse_speakers) {
4111 adev->speaker_lr_swap = reverse_speakers;
4112 // only update the selected device if there is active pcm playback
4113 struct audio_usecase *usecase;
4114 struct listnode *node;
4115 list_for_each(node, &adev->usecase_list) {
4116 usecase = node_to_item(node, struct audio_usecase, list);
4117 if (usecase->type == PCM_PLAYBACK) {
4118 select_devices(adev, usecase->id);
4119 break;
4120 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004121 }
4122 }
4123 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004124 }
4125
Mingming Yin514a8bc2014-07-29 15:22:21 -07004126 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4127 if (ret >= 0) {
4128 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4129 adev->bt_wb_speech_enabled = true;
4130 else
4131 adev->bt_wb_speech_enabled = false;
4132 }
4133
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004134 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4135 if (ret >= 0) {
4136 val = atoi(value);
4137 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004138 ALOGV("cache new ext disp type and edid");
4139 ret = platform_get_ext_disp_type(adev->platform);
4140 if (ret < 0) {
4141 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4142 return ret;
4143 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004144 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004145 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004146 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004147 /*
4148 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4149 * Per AudioPolicyManager, USB device is higher priority than WFD.
4150 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4151 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4152 * starting voice call on USB
4153 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004154 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4155 if (ret >= 0) {
4156 audio_extn_usb_add_device(val, atoi(value));
4157 }
vivek mehta344576a2016-04-12 18:56:03 -07004158 ALOGV("detected USB connect .. disable proxy");
4159 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004160 }
4161 }
4162
4163 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4164 if (ret >= 0) {
4165 val = atoi(value);
4166 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4167 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004168 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004169 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004170 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004171 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4172 if (ret >= 0) {
4173 audio_extn_usb_remove_device(val, atoi(value));
4174 }
vivek mehta344576a2016-04-12 18:56:03 -07004175 ALOGV("detected USB disconnect .. enable proxy");
4176 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004177 }
4178 }
4179
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304180 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4181 if (ret >= 0) {
4182 struct audio_usecase *usecase;
4183 struct listnode *node;
4184 list_for_each(node, &adev->usecase_list) {
4185 usecase = node_to_item(node, struct audio_usecase, list);
4186 if ((usecase->type == PCM_PLAYBACK) &&
4187 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4188 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304189 lock_output_stream(usecase->stream.out);
4190 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304191 //force device switch to re configure encoder
4192 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304193 audio_extn_a2dp_set_handoff_mode(false);
4194 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304195 break;
4196 }
4197 }
4198 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304199 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004200done:
4201 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004202 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304203error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004204 ALOGV("%s: exit with code(%d)", __func__, status);
4205 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206}
4207
4208static char* adev_get_parameters(const struct audio_hw_device *dev,
4209 const char *keys)
4210{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004211 struct audio_device *adev = (struct audio_device *)dev;
4212 struct str_parms *reply = str_parms_create();
4213 struct str_parms *query = str_parms_create_str(keys);
4214 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304215 char value[256] = {0};
4216 int ret = 0;
4217
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004218 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004219 if (reply) {
4220 str_parms_destroy(reply);
4221 }
4222 if (query) {
4223 str_parms_destroy(query);
4224 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004225 ALOGE("adev_get_parameters: failed to create query or reply");
4226 return NULL;
4227 }
4228
Naresh Tannirud7205b62014-06-20 02:54:48 +05304229 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4230 sizeof(value));
4231 if (ret >=0) {
4232 int val = 1;
4233 pthread_mutex_lock(&adev->snd_card_status.lock);
4234 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4235 val = 0;
4236 pthread_mutex_unlock(&adev->snd_card_status.lock);
4237 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4238 goto exit;
4239 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004240
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004241 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004242 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004243 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004244 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304245 pthread_mutex_unlock(&adev->lock);
4246
Naresh Tannirud7205b62014-06-20 02:54:48 +05304247exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004248 str = str_parms_to_str(reply);
4249 str_parms_destroy(query);
4250 str_parms_destroy(reply);
4251
4252 ALOGV("%s: exit: returns - %s", __func__, str);
4253 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254}
4255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004256static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257{
4258 return 0;
4259}
4260
4261static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4262{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004263 int ret;
4264 struct audio_device *adev = (struct audio_device *)dev;
4265 pthread_mutex_lock(&adev->lock);
4266 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004267 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004268 pthread_mutex_unlock(&adev->lock);
4269 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270}
4271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004272static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4273 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274{
4275 return -ENOSYS;
4276}
4277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004278static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4279 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280{
4281 return -ENOSYS;
4282}
4283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004284static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4285 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286{
4287 return -ENOSYS;
4288}
4289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004290static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4291 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292{
4293 return -ENOSYS;
4294}
4295
4296static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4297{
4298 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 pthread_mutex_lock(&adev->lock);
4301 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004302 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004304 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004305 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004306 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004307 adev->current_call_output = NULL;
4308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 }
4310 pthread_mutex_unlock(&adev->lock);
4311 return 0;
4312}
4313
4314static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4315{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004316 int ret;
4317
4318 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004319 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004320 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4321 pthread_mutex_unlock(&adev->lock);
4322
4323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324}
4325
4326static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4327{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004328 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 return 0;
4330}
4331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004332static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 const struct audio_config *config)
4334{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004335 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004337 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4338 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339}
4340
4341static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004342 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 audio_devices_t devices,
4344 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004345 struct audio_stream_in **stream_in,
4346 audio_input_flags_t flags __unused,
4347 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004348 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349{
4350 struct audio_device *adev = (struct audio_device *)dev;
4351 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004352 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004353 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004354 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304357 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4358 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361
4362 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004363
4364 if (!in) {
4365 ALOGE("failed to allocate input stream");
4366 return -ENOMEM;
4367 }
4368
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304369 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304370 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4371 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004372 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004373 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 in->stream.common.get_sample_rate = in_get_sample_rate;
4376 in->stream.common.set_sample_rate = in_set_sample_rate;
4377 in->stream.common.get_buffer_size = in_get_buffer_size;
4378 in->stream.common.get_channels = in_get_channels;
4379 in->stream.common.get_format = in_get_format;
4380 in->stream.common.set_format = in_set_format;
4381 in->stream.common.standby = in_standby;
4382 in->stream.common.dump = in_dump;
4383 in->stream.common.set_parameters = in_set_parameters;
4384 in->stream.common.get_parameters = in_get_parameters;
4385 in->stream.common.add_audio_effect = in_add_audio_effect;
4386 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4387 in->stream.set_gain = in_set_gain;
4388 in->stream.read = in_read;
4389 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4390
4391 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004392 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 in->standby = 1;
4395 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004396 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004397 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398
4399 /* Update config params with the requested sample rate and channels */
4400 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004401 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4402 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4403 is_low_latency = true;
4404#if LOW_LATENCY_CAPTURE_USE_CASE
4405 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4406#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004407 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004408 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004409
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004410 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004411 if (in->realtime) {
4412 in->config = pcm_config_audio_capture_rt;
4413 in->sample_rate = in->config.rate;
4414 in->af_period_multiplier = af_period_multiplier;
4415 } else {
4416 in->config = pcm_config_audio_capture;
4417 in->config.rate = config->sample_rate;
4418 in->sample_rate = config->sample_rate;
4419 in->af_period_multiplier = 1;
4420 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304421 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004423 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304424 if (adev->mode != AUDIO_MODE_IN_CALL) {
4425 ret = -EINVAL;
4426 goto err_open;
4427 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004428 if (config->sample_rate == 0)
4429 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4430 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4431 config->sample_rate != 8000) {
4432 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4433 ret = -EINVAL;
4434 goto err_open;
4435 }
4436 if (config->format == AUDIO_FORMAT_DEFAULT)
4437 config->format = AUDIO_FORMAT_PCM_16_BIT;
4438 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4439 config->format = AUDIO_FORMAT_PCM_16_BIT;
4440 ret = -EINVAL;
4441 goto err_open;
4442 }
4443
4444 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4445 in->config = pcm_config_afe_proxy_record;
4446 in->config.channels = channel_count;
4447 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304448 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304449 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4450 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004451 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004452 audio_extn_compr_cap_format_supported(config->format) &&
4453 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004454 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004455 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304456 /* restrict 24 bit capture for unprocessed source only
4457 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4458 */
4459 if (config->format == AUDIO_FORMAT_DEFAULT) {
4460 config->format = AUDIO_FORMAT_PCM_16_BIT;
4461 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4462 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4463 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4464 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4465 bool ret_error = false;
4466 in->bit_width = 24;
4467 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4468 from HAL is 24_packed and 8_24
4469 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4470 24_packed return error indicating supported format is 24_packed
4471 *> In case of any other source requesting 24 bit or float return error
4472 indicating format supported is 16 bit only.
4473
4474 on error flinger will retry with supported format passed
4475 */
4476 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4477 (source != AUDIO_SOURCE_CAMCORDER)) {
4478 config->format = AUDIO_FORMAT_PCM_16_BIT;
4479 if( config->sample_rate > 48000)
4480 config->sample_rate = 48000;
4481 ret_error = true;
4482 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4483 in->config.format = PCM_FORMAT_S24_3LE;
4484 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4485 in->config.format = PCM_FORMAT_S24_LE;
4486 } else {
4487 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4488 ret_error = true;
4489 }
4490
4491 if (ret_error) {
4492 ret = -EINVAL;
4493 goto err_open;
4494 }
4495 }
4496
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004497 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004498 if (!in->realtime) {
4499 in->format = config->format;
4500 frame_size = audio_stream_in_frame_size(&in->stream);
4501 buffer_size = get_input_buffer_size(config->sample_rate,
4502 config->format,
4503 channel_count,
4504 is_low_latency);
4505 in->config.period_size = buffer_size / frame_size;
4506 }
4507
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004508 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4509 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4510 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004511 (in->config.rate == 8000 || in->config.rate == 16000 ||
4512 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004513 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4514 voice_extn_compress_voip_open_input_stream(in);
4515 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004518 /* This stream could be for sound trigger lab,
4519 get sound trigger pcm if present */
4520 audio_extn_sound_trigger_check_and_get_session(in);
4521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004523 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004524 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525
4526err_open:
4527 free(in);
4528 *stream_in = NULL;
4529 return ret;
4530}
4531
4532static void adev_close_input_stream(struct audio_hw_device *dev,
4533 struct audio_stream_in *stream)
4534{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004535 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004536 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004537 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304538
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304539 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004540
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304541 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004542 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304543
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004544 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304545 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004546 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304547 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004548 if (ret != 0)
4549 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4550 __func__, ret);
4551 } else
4552 in_standby(&stream->common);
4553
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004554 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004555 audio_extn_ssr_deinit();
4556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557
Mingming Yine62d7842013-10-25 16:26:03 -07004558 if(audio_extn_compr_cap_enabled() &&
4559 audio_extn_compr_cap_format_supported(in->config.format))
4560 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004561
Mingming Yinfd7607b2016-01-22 12:48:44 -08004562 if (in->is_st_session) {
4563 ALOGV("%s: sound trigger pcm stop lab", __func__);
4564 audio_extn_sound_trigger_stop_lab(in);
4565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004566 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 return;
4568}
4569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004570static int adev_dump(const audio_hw_device_t *device __unused,
4571 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572{
4573 return 0;
4574}
4575
4576static int adev_close(hw_device_t *device)
4577{
4578 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004579
4580 if (!adev)
4581 return 0;
4582
4583 pthread_mutex_lock(&adev_init_lock);
4584
4585 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004586 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004587 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304588 if (audio_extn_qaf_is_enabled())
4589 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004590 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004591 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004592 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004593 free(adev->snd_dev_ref_cnt);
4594 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004595 if (adev->adm_deinit)
4596 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004597 free(device);
4598 adev = NULL;
4599 }
4600 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 return 0;
4603}
4604
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004605/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4606 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4607 * just that it _might_ work.
4608 */
4609static int period_size_is_plausible_for_low_latency(int period_size)
4610{
4611 switch (period_size) {
4612 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004613 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004614 case 240:
4615 case 320:
4616 case 480:
4617 return 1;
4618 default:
4619 return 0;
4620 }
4621}
4622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623static int adev_open(const hw_module_t *module, const char *name,
4624 hw_device_t **device)
4625{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304626 int ret;
4627
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004628 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4630
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004631 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004632 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004633 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004634 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004635 ALOGD("%s: returning existing instance of adev", __func__);
4636 ALOGD("%s: exit", __func__);
4637 pthread_mutex_unlock(&adev_init_lock);
4638 return 0;
4639 }
4640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 adev = calloc(1, sizeof(struct audio_device));
4642
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004643 if (!adev) {
4644 pthread_mutex_unlock(&adev_init_lock);
4645 return -ENOMEM;
4646 }
4647
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004648 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4651 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4652 adev->device.common.module = (struct hw_module_t *)module;
4653 adev->device.common.close = adev_close;
4654
4655 adev->device.init_check = adev_init_check;
4656 adev->device.set_voice_volume = adev_set_voice_volume;
4657 adev->device.set_master_volume = adev_set_master_volume;
4658 adev->device.get_master_volume = adev_get_master_volume;
4659 adev->device.set_master_mute = adev_set_master_mute;
4660 adev->device.get_master_mute = adev_get_master_mute;
4661 adev->device.set_mode = adev_set_mode;
4662 adev->device.set_mic_mute = adev_set_mic_mute;
4663 adev->device.get_mic_mute = adev_get_mic_mute;
4664 adev->device.set_parameters = adev_set_parameters;
4665 adev->device.get_parameters = adev_get_parameters;
4666 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4667 adev->device.open_output_stream = adev_open_output_stream;
4668 adev->device.close_output_stream = adev_close_output_stream;
4669 adev->device.open_input_stream = adev_open_input_stream;
4670 adev->device.close_input_stream = adev_close_input_stream;
4671 adev->device.dump = adev_dump;
4672
4673 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004675 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004676 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004679 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004680 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004681 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004682 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004683 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004684 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004685 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004686 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304687 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304688 adev->perf_lock_opts[0] = 0x101;
4689 adev->perf_lock_opts[1] = 0x20E;
4690 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304691
4692 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4693 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004695 adev->platform = platform_init(adev);
4696 if (!adev->platform) {
4697 free(adev->snd_dev_ref_cnt);
4698 free(adev);
4699 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4700 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004701 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304702 pthread_mutex_destroy(&adev->lock);
4703 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004704 return -EINVAL;
4705 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004706
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304707 if (audio_extn_qaf_is_enabled()) {
4708 ret = audio_extn_qaf_init(adev);
4709 if (ret < 0) {
4710 free(adev);
4711 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4712 *device = NULL;
4713 pthread_mutex_unlock(&adev_init_lock);
4714 pthread_mutex_destroy(&adev->lock);
4715 return ret;
4716 }
4717
4718 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4719 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4720 }
4721
Naresh Tanniru4c630392014-05-12 01:05:52 +05304722 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4723
Eric Laurentc4aef752013-09-12 17:45:53 -07004724 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4725 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4726 if (adev->visualizer_lib == NULL) {
4727 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4728 } else {
4729 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4730 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004731 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004732 "visualizer_hal_start_output");
4733 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004734 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004735 "visualizer_hal_stop_output");
4736 }
4737 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004738 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004739 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004740 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004741
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004742 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4743 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4744 if (adev->offload_effects_lib == NULL) {
4745 ALOGE("%s: DLOPEN failed for %s", __func__,
4746 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4747 } else {
4748 ALOGV("%s: DLOPEN successful for %s", __func__,
4749 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4750 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304751 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004752 "offload_effects_bundle_hal_start_output");
4753 adev->offload_effects_stop_output =
4754 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4755 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004756 adev->offload_effects_set_hpx_state =
4757 (int (*)(bool))dlsym(adev->offload_effects_lib,
4758 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304759 adev->offload_effects_get_parameters =
4760 (void (*)(struct str_parms *, struct str_parms *))
4761 dlsym(adev->offload_effects_lib,
4762 "offload_effects_bundle_get_parameters");
4763 adev->offload_effects_set_parameters =
4764 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4765 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004766 }
4767 }
4768
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004769 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4770 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4771 if (adev->adm_lib == NULL) {
4772 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4773 } else {
4774 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4775 adev->adm_init = (adm_init_t)
4776 dlsym(adev->adm_lib, "adm_init");
4777 adev->adm_deinit = (adm_deinit_t)
4778 dlsym(adev->adm_lib, "adm_deinit");
4779 adev->adm_register_input_stream = (adm_register_input_stream_t)
4780 dlsym(adev->adm_lib, "adm_register_input_stream");
4781 adev->adm_register_output_stream = (adm_register_output_stream_t)
4782 dlsym(adev->adm_lib, "adm_register_output_stream");
4783 adev->adm_deregister_stream = (adm_deregister_stream_t)
4784 dlsym(adev->adm_lib, "adm_deregister_stream");
4785 adev->adm_request_focus = (adm_request_focus_t)
4786 dlsym(adev->adm_lib, "adm_request_focus");
4787 adev->adm_abandon_focus = (adm_abandon_focus_t)
4788 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004789 adev->adm_set_config = (adm_set_config_t)
4790 dlsym(adev->adm_lib, "adm_set_config");
4791 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4792 dlsym(adev->adm_lib, "adm_request_focus_v2");
4793 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4794 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4795 adev->adm_on_routing_change = (adm_on_routing_change_t)
4796 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004797 }
4798 }
4799
Mingming Yin514a8bc2014-07-29 15:22:21 -07004800 adev->bt_wb_speech_enabled = false;
4801
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004802 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803 *device = &adev->device.common;
4804
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004805 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4806 &adev->streams_output_cfg_list);
4807
Kiran Kandi910e1862013-10-29 13:29:42 -07004808 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004809
4810 char value[PROPERTY_VALUE_MAX];
4811 int trial;
4812 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4813 trial = atoi(value);
4814 if (period_size_is_plausible_for_low_latency(trial)) {
4815 pcm_config_low_latency.period_size = trial;
4816 pcm_config_low_latency.start_threshold = trial / 4;
4817 pcm_config_low_latency.avail_min = trial / 4;
4818 configured_low_latency_capture_period_size = trial;
4819 }
4820 }
4821 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4822 trial = atoi(value);
4823 if (period_size_is_plausible_for_low_latency(trial)) {
4824 configured_low_latency_capture_period_size = trial;
4825 }
4826 }
4827
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004828 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4829 af_period_multiplier = atoi(value);
4830 if (af_period_multiplier < 0)
4831 af_period_multiplier = 2;
4832 else if (af_period_multiplier > 4)
4833 af_period_multiplier = 4;
4834
4835 ALOGV("new period_multiplier = %d", af_period_multiplier);
4836 }
4837
vivek mehta446c3962015-09-14 10:57:35 -07004838 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004839 pthread_mutex_unlock(&adev_init_lock);
4840
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004841 if (adev->adm_init)
4842 adev->adm_data = adev->adm_init();
4843
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304844 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004845 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 return 0;
4847}
4848
4849static struct hw_module_methods_t hal_module_methods = {
4850 .open = adev_open,
4851};
4852
4853struct audio_module HAL_MODULE_INFO_SYM = {
4854 .common = {
4855 .tag = HARDWARE_MODULE_TAG,
4856 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4857 .hal_api_version = HARDWARE_HAL_API_VERSION,
4858 .id = AUDIO_HARDWARE_MODULE_ID,
4859 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004860 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 .methods = &hal_module_methods,
4862 },
4863};