blob: a7a8d19fdda83e15bb90cec7d233f894474b7f20 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530799 } else if (platform_can_split_snd_device(adev->platform, snd_device,
800 &num_devices, new_snd_devices)) {
801 for (i = 0; i < num_devices; i++) {
802 enable_snd_device(adev, new_snd_devices[i]);
803 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700805 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530806
807 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
808 (audio_extn_a2dp_start_playback() < 0)) {
809 ALOGE(" fail to configure A2dp control path ");
810 return -EINVAL;
811 }
812
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700813 /* due to the possibility of calibration overwrite between listen
814 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700815 audio_extn_sound_trigger_update_device_status(snd_device,
816 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530817 audio_extn_listen_update_device_status(snd_device,
818 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700819 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700820 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700821 audio_extn_sound_trigger_update_device_status(snd_device,
822 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530823 audio_extn_listen_update_device_status(snd_device,
824 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700825 return -EINVAL;
826 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300827 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700828 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530829
830 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
831 !adev->native_playback_enabled &&
832 audio_is_true_native_stream_active(adev)) {
833 ALOGD("%s: %d: napb: enabling native mode in hardware",
834 __func__, __LINE__);
835 audio_route_apply_and_update_path(adev->audio_route,
836 "true-native-mode");
837 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840 return 0;
841}
842
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700843int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700844 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530846 int i, num_devices = 0;
847 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700848 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
849
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 if (snd_device < SND_DEVICE_MIN ||
851 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800853 return -EINVAL;
854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
856 ALOGE("%s: device ref cnt is already 0", __func__);
857 return -EINVAL;
858 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700861
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
863 ALOGE("%s: Invalid sound device returned", __func__);
864 return -EINVAL;
865 }
866
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700868 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530869
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800870 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
871 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700872 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 } else if (platform_can_split_snd_device(adev->platform, snd_device,
874 &num_devices, new_snd_devices)) {
875 for (i = 0; i < num_devices; i++) {
876 disable_snd_device(adev, new_snd_devices[i]);
877 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300878 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700879 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300880 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700881
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530882 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
883 audio_extn_a2dp_stop_playback();
884
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700885 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530886 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530887 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
888 adev->native_playback_enabled) {
889 ALOGD("%s: %d: napb: disabling native mode in hardware",
890 __func__, __LINE__);
891 audio_route_reset_and_update_path(adev->audio_route,
892 "true-native-mode");
893 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530894 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
895 adev->asrc_mode_enabled) {
896 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530897 disable_asrc_mode(adev);
898 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530899 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200901 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700902 audio_extn_sound_trigger_update_device_status(snd_device,
903 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530904 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800905 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 return 0;
909}
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530919 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /*
921 * This function is to make sure that all the usecases that are active on
922 * the hardware codec backend are always routed to any one device that is
923 * handled by the hardware codec.
924 * For example, if low-latency and deep-buffer usecases are currently active
925 * on speaker and out_set_parameters(headset) is received on low-latency
926 * output, then we have to make sure deep-buffer is also switched to headset,
927 * because of the limitation that both the devices cannot be enabled
928 * at the same time as they share the same backend.
929 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700930 /*
931 * This call is to check if we need to force routing for a particular stream
932 * If there is a backend configuration change for the device when a
933 * new stream starts, then ADM needs to be closed and re-opened with the new
934 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800935 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700936 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800937 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
938 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530939 /* For a2dp device reconfigure all active sessions
940 * with new AFE encoder format based on a2dp state
941 */
942 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
943 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
944 audio_extn_a2dp_is_force_device_switch()) {
945 force_routing = true;
946 force_restart_session = true;
947 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530948 ALOGD("%s:becf: force routing %d", __func__, force_routing);
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800952 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
954 switch_device[i] = false;
955
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800958
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530959 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
960 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530962 platform_get_snd_device_name(usecase->out_snd_device),
963 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800964 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530965 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530966 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530967 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
968 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530969 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530970 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530971 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
972
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530973 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
974 __func__, use_case_table[usecase->id],
975 platform_get_snd_device_name(usecase->out_snd_device));
976 disable_audio_route(adev, usecase);
977 switch_device[usecase->id] = true;
978 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980 }
981
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
983 num_uc_to_switch);
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700986 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530988 /* Make sure the previous devices to be disabled first and then enable the
989 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 list_for_each(node, &adev->usecase_list) {
991 usecase = node_to_item(node, struct audio_usecase, list);
992 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700993 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 }
995 }
996
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700997 list_for_each(node, &adev->usecase_list) {
998 usecase = node_to_item(node, struct audio_usecase, list);
999 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001000 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 /* Re-route all the usecases on the shared backend other than the
1005 specified usecase to new snd devices */
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301008 /* Update the out_snd_device only before enabling the audio route */
1009 if (switch_device[usecase->id]) {
1010 usecase->out_snd_device = snd_device;
1011 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301012 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301013 use_case_table[usecase->id],
1014 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301015 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 }
1018 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 }
1020}
1021
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301022static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001023 struct audio_usecase *uc_info,
1024 snd_device_t snd_device)
1025{
1026 struct listnode *node;
1027 struct audio_usecase *usecase;
1028 bool switch_device[AUDIO_USECASE_MAX];
1029 int i, num_uc_to_switch = 0;
1030
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301031 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1032 snd_device);
1033 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034 /*
1035 * This function is to make sure that all the active capture usecases
1036 * are always routed to the same input sound device.
1037 * For example, if audio-record and voice-call usecases are currently
1038 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1039 * is received for voice call then we have to make sure that audio-record
1040 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1041 * because of the limitation that two devices cannot be enabled
1042 * at the same time if they share the same backend.
1043 */
1044 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1045 switch_device[i] = false;
1046
1047 list_for_each(node, &adev->usecase_list) {
1048 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001049 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301051 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001052 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301053 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001054 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001055 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001058 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
1062 }
1063 }
1064
1065 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001066 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001067
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301068 /* Make sure the previous devices to be disabled first and then enable the
1069 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001070 list_for_each(node, &adev->usecase_list) {
1071 usecase = node_to_item(node, struct audio_usecase, list);
1072 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001073 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001074 }
1075 }
1076
1077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 }
1082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 /* Re-route all the usecases on the shared backend other than the
1085 specified usecase to new snd devices */
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 /* Update the in_snd_device only before enabling the audio route */
1089 if (switch_device[usecase->id] ) {
1090 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001091 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301092 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001093 }
1094 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001095 }
1096}
1097
Mingming Yin3a941d42016-02-17 18:08:05 -08001098static void reset_hdmi_sink_caps(struct stream_out *out) {
1099 int i = 0;
1100
1101 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1102 out->supported_channel_masks[i] = 0;
1103 }
1104 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1105 out->supported_formats[i] = 0;
1106 }
1107 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1108 out->supported_sample_rates[i] = 0;
1109 }
1110}
1111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001113static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114{
Mingming Yin3a941d42016-02-17 18:08:05 -08001115 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001116 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Mingming Yin3a941d42016-02-17 18:08:05 -08001118 reset_hdmi_sink_caps(out);
1119
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001120 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001121 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001122 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001123 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001124 }
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001129 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001130 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1131 case 6:
1132 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1133 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1134 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1135 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1136 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1137 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 break;
1139 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001140 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001141 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 break;
1143 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001144
1145 // check channel format caps
1146 i = 0;
1147 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1148 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1149 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1150 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1151 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1152 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1153 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1154 }
1155
1156 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1157 ALOGV(":%s HDMI supports DTS format", __func__);
1158 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1159 }
1160
1161 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1162 ALOGV(":%s HDMI supports DTS HD format", __func__);
1163 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1164 }
1165
1166
1167 // check sample rate caps
1168 i = 0;
1169 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1170 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1171 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1172 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1173 }
1174 }
1175
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001176 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177}
1178
Alexy Josephb1379942016-01-29 15:49:38 -08001179audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001180 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001181{
1182 struct audio_usecase *usecase;
1183 struct listnode *node;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001187 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001188 ALOGV("%s: usecase id %d", __func__, usecase->id);
1189 return usecase->id;
1190 }
1191 }
1192 return USECASE_INVALID;
1193}
1194
Alexy Josephb1379942016-01-29 15:49:38 -08001195struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001196 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197{
1198 struct audio_usecase *usecase;
1199 struct listnode *node;
1200
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (usecase->id == uc_id)
1204 return usecase;
1205 }
1206 return NULL;
1207}
1208
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209/*
1210 * is a true native playback active
1211 */
1212bool audio_is_true_native_stream_active(struct audio_device *adev)
1213{
1214 bool active = false;
1215 int i = 0;
1216 struct listnode *node;
1217
1218 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1219 ALOGV("%s:napb: not in true mode or non hdphones device",
1220 __func__);
1221 active = false;
1222 goto exit;
1223 }
1224
1225 list_for_each(node, &adev->usecase_list) {
1226 struct audio_usecase *uc;
1227 uc = node_to_item(node, struct audio_usecase, list);
1228 struct stream_out *curr_out =
1229 (struct stream_out*) uc->stream.out;
1230
1231 if (curr_out && PCM_PLAYBACK == uc->type) {
1232 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1233 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1234 uc->id, curr_out->sample_rate,
1235 curr_out->bit_width,
1236 platform_get_snd_device_name(uc->out_snd_device));
1237
1238 if (is_offload_usecase(uc->id) &&
1239 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1240 active = true;
1241 ALOGD("%s:napb:native stream detected", __func__);
1242 }
1243 }
1244 }
1245exit:
1246 return active;
1247}
1248
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301249/*
1250 * if native DSD playback active
1251 */
1252bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1253{
1254 bool active = false;
1255 struct listnode *node = NULL;
1256 struct audio_usecase *uc = NULL;
1257 struct stream_out *curr_out = NULL;
1258
1259 list_for_each(node, &adev->usecase_list) {
1260 uc = node_to_item(node, struct audio_usecase, list);
1261 curr_out = (struct stream_out*) uc->stream.out;
1262
1263 if (curr_out && PCM_PLAYBACK == uc->type &&
1264 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1265 active = true;
1266 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301267 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301268 }
1269 }
1270 return active;
1271}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301272
1273static bool force_device_switch(struct audio_usecase *usecase)
1274{
1275 bool ret = false;
1276 bool is_it_true_mode = false;
1277
1278 if (is_offload_usecase(usecase->id) &&
1279 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001280 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1281 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1282 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301283 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1284 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1285 (!is_it_true_mode && adev->native_playback_enabled)){
1286 ret = true;
1287 ALOGD("napb: time to toggle native mode");
1288 }
1289 }
1290
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301291 // Force all a2dp output devices to reconfigure for proper AFE encode format
1292 if((usecase->stream.out) &&
1293 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1294 audio_extn_a2dp_is_force_device_switch()) {
1295 ALOGD("Force a2dp device switch to update new encoder config");
1296 ret = true;
1297 }
1298
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301299 return ret;
1300}
1301
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001302int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001304 snd_device_t out_snd_device = SND_DEVICE_NONE;
1305 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 struct audio_usecase *usecase = NULL;
1307 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001308 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001309 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001310 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301313 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1314
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 usecase = get_usecase_from_list(adev, uc_id);
1316 if (usecase == NULL) {
1317 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1318 return -EINVAL;
1319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001321 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001322 (usecase->type == VOIP_CALL) ||
1323 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001324 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001325 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001326 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 usecase->devices = usecase->stream.out->devices;
1328 } else {
1329 /*
1330 * If the voice call is active, use the sound devices of voice call usecase
1331 * so that it would not result any device switch. All the usecases will
1332 * be switched to new device when select_devices() is called for voice call
1333 * usecase. This is to avoid switching devices for voice call when
1334 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001335 * choose voice call device only if the use case device is
1336 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001338 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001339 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001340 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001341 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1342 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301343 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1344 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001345 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001346 in_snd_device = vc_usecase->in_snd_device;
1347 out_snd_device = vc_usecase->out_snd_device;
1348 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001349 } else if (voice_extn_compress_voip_is_active(adev)) {
1350 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001351 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001352 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1353 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001354 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001355 in_snd_device = voip_usecase->in_snd_device;
1356 out_snd_device = voip_usecase->out_snd_device;
1357 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001358 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001359 hfp_ucid = audio_extn_hfp_get_usecase();
1360 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001361 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001362 in_snd_device = hfp_usecase->in_snd_device;
1363 out_snd_device = hfp_usecase->out_snd_device;
1364 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365 }
1366 if (usecase->type == PCM_PLAYBACK) {
1367 usecase->devices = usecase->stream.out->devices;
1368 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001369 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001370 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001371 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001372 if (usecase->stream.out == adev->primary_output &&
1373 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001374 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001375 select_devices(adev, adev->active_input->usecase);
1376 }
1377 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 } else if (usecase->type == PCM_CAPTURE) {
1379 usecase->devices = usecase->stream.in->device;
1380 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001381 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001382 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001383 if (adev->active_input &&
1384 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301385 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1386 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1387 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001388 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001389 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001390 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1391 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001392 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001393 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001394 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001395 }
1396 }
1397
1398 if (out_snd_device == usecase->out_snd_device &&
1399 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301400
1401 if (!force_device_switch(usecase))
1402 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 }
1404
sangwoobc677242013-08-08 16:53:43 +09001405 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001406 out_snd_device, platform_get_snd_device_name(out_snd_device),
1407 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409 /*
1410 * Limitation: While in call, to do a device switch we need to disable
1411 * and enable both RX and TX devices though one of them is same as current
1412 * device.
1413 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001414 if ((usecase->type == VOICE_CALL) &&
1415 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1416 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001417 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001418 }
1419
1420 if (((usecase->type == VOICE_CALL) ||
1421 (usecase->type == VOIP_CALL)) &&
1422 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1423 /* Disable sidetone only if voice/voip call already exists */
1424 if (voice_is_call_state_active(adev) ||
1425 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001426 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001427 }
1428
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429 /* Disable current sound devices */
1430 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001431 disable_audio_route(adev, usecase);
1432 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 }
1434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001436 disable_audio_route(adev, usecase);
1437 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 }
1439
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001440 /* Applicable only on the targets that has external modem.
1441 * New device information should be sent to modem before enabling
1442 * the devices to reduce in-call device switch time.
1443 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001444 if ((usecase->type == VOICE_CALL) &&
1445 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1446 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001447 status = platform_switch_voice_call_enable_device_config(adev->platform,
1448 out_snd_device,
1449 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001450 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001451
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452 /* Enable new sound devices */
1453 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001454 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301455 if (platform_check_codec_asrc_support(adev->platform))
1456 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001457 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 }
1459
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001460 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301461 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001463 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464
Avinash Vaish71a8b972014-07-24 15:36:33 +05301465 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001466 status = platform_switch_voice_call_device_post(adev->platform,
1467 out_snd_device,
1468 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301469 enable_audio_route_for_voice_usecases(adev, usecase);
1470 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001471
sangwoo170731f2013-06-08 15:36:36 +09001472 usecase->in_snd_device = in_snd_device;
1473 usecase->out_snd_device = out_snd_device;
1474
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301475 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001476 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301477 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001478 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301479 usecase->stream.out->flags,
1480 usecase->stream.out->format,
1481 usecase->stream.out->sample_rate,
1482 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301483 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301484 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001485 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001486
1487 /* Notify device change info to effect clients registered */
1488 audio_extn_gef_notify_device_config(
1489 usecase->stream.out->devices,
1490 usecase->stream.out->channel_mask,
1491 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301492 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001493
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001494 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001495
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001496 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1497 /* Enable sidetone only if other voice/voip call already exists */
1498 if (voice_is_call_state_active(adev) ||
1499 voice_extn_compress_voip_is_started(adev))
1500 voice_set_sidetone(adev, out_snd_device, true);
1501 }
1502
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001503 /* Applicable only on the targets that has external modem.
1504 * Enable device command should be sent to modem only after
1505 * enabling voice call mixer controls
1506 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001507 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001508 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1509 out_snd_device,
1510 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301511 ALOGD("%s: done",__func__);
1512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 return status;
1514}
1515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516static int stop_input_stream(struct stream_in *in)
1517{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301518 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 struct audio_usecase *uc_info;
1520 struct audio_device *adev = in->dev;
1521
Eric Laurentc8400632013-02-14 19:04:54 -08001522 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Eric Laurent994a6932013-07-17 11:51:42 -07001524 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 uc_info = get_usecase_from_list(adev, in->usecase);
1527 if (uc_info == NULL) {
1528 ALOGE("%s: Could not find the usecase (%d) in the list",
1529 __func__, in->usecase);
1530 return -EINVAL;
1531 }
1532
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001533 /* Close in-call recording streams */
1534 voice_check_and_stop_incall_rec_usecase(adev, in);
1535
Eric Laurent150dbfe2013-02-27 14:31:02 -08001536 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001537 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538
1539 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001540 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001542 list_remove(&uc_info->list);
1543 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Eric Laurent994a6932013-07-17 11:51:42 -07001545 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 return ret;
1547}
1548
1549int start_input_stream(struct stream_in *in)
1550{
1551 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001552 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 struct audio_usecase *uc_info;
1554 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301555 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Mingming Yin2664a5b2015-09-03 10:53:11 -07001557 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1558 if (get_usecase_from_list(adev, usecase) == NULL)
1559 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301560 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1561 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001562
Naresh Tanniru80659832014-06-04 18:17:56 +05301563
1564 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301565 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301566 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301567 goto error_config;
1568 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301569
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001570 /* Check if source matches incall recording usecase criteria */
1571 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1572 if (ret)
1573 goto error_config;
1574 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001575 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1576
1577 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1578 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1579 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001580 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001581 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001582
Eric Laurentb23d5282013-05-14 15:27:20 -07001583 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 if (in->pcm_device_id < 0) {
1585 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1586 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001587 ret = -EINVAL;
1588 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590
1591 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001593
1594 if (!uc_info) {
1595 ret = -ENOMEM;
1596 goto error_config;
1597 }
1598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599 uc_info->id = in->usecase;
1600 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001601 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001602 uc_info->devices = in->device;
1603 uc_info->in_snd_device = SND_DEVICE_NONE;
1604 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001606 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301607 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1608 adev->perf_lock_opts,
1609 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301612 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1613 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001614
1615 unsigned int flags = PCM_IN;
1616 unsigned int pcm_open_retry_count = 0;
1617
1618 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1619 flags |= PCM_MMAP | PCM_NOIRQ;
1620 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001621 } else if (in->realtime) {
1622 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001623 }
1624
1625 while (1) {
1626 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1627 flags, &in->config);
1628 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1629 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1630 if (in->pcm != NULL) {
1631 pcm_close(in->pcm);
1632 in->pcm = NULL;
1633 }
1634 if (pcm_open_retry_count-- == 0) {
1635 ret = -EIO;
1636 goto error_open;
1637 }
1638 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1639 continue;
1640 }
1641 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001643
1644 ALOGV("%s: pcm_prepare", __func__);
1645 ret = pcm_prepare(in->pcm);
1646 if (ret < 0) {
1647 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1648 pcm_close(in->pcm);
1649 in->pcm = NULL;
1650 goto error_open;
1651 }
1652
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001653 register_in_stream(in);
1654 if (in->realtime) {
1655 ret = pcm_start(in->pcm);
1656 if (ret < 0)
1657 goto error_open;
1658 }
1659
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301660 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001661 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001662
Eric Laurentc8400632013-02-14 19:04:54 -08001663 return ret;
1664
1665error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301666 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001668error_config:
1669 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301670 /*
1671 * sleep 50ms to allow sufficient time for kernel
1672 * drivers to recover incases like SSR.
1673 */
1674 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001676
1677 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001680void lock_input_stream(struct stream_in *in)
1681{
1682 pthread_mutex_lock(&in->pre_lock);
1683 pthread_mutex_lock(&in->lock);
1684 pthread_mutex_unlock(&in->pre_lock);
1685}
1686
1687void lock_output_stream(struct stream_out *out)
1688{
1689 pthread_mutex_lock(&out->pre_lock);
1690 pthread_mutex_lock(&out->lock);
1691 pthread_mutex_unlock(&out->pre_lock);
1692}
1693
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001694/* must be called with out->lock locked */
1695static int send_offload_cmd_l(struct stream_out* out, int command)
1696{
1697 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1698
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001699 if (!cmd) {
1700 ALOGE("failed to allocate mem for command 0x%x", command);
1701 return -ENOMEM;
1702 }
1703
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001704 ALOGVV("%s %d", __func__, command);
1705
1706 cmd->cmd = command;
1707 list_add_tail(&out->offload_cmd_list, &cmd->node);
1708 pthread_cond_signal(&out->offload_cond);
1709 return 0;
1710}
1711
1712/* must be called iwth out->lock locked */
1713static void stop_compressed_output_l(struct stream_out *out)
1714{
1715 out->offload_state = OFFLOAD_STATE_IDLE;
1716 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001717 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 if (out->compr != NULL) {
1719 compress_stop(out->compr);
1720 while (out->offload_thread_blocked) {
1721 pthread_cond_wait(&out->cond, &out->lock);
1722 }
1723 }
1724}
1725
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726bool is_offload_usecase(audio_usecase_t uc_id)
1727{
1728 unsigned int i;
1729 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1730 if (uc_id == offload_usecases[i])
1731 return true;
1732 }
1733 return false;
1734}
1735
vivek mehta446c3962015-09-14 10:57:35 -07001736static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001737{
vivek mehta446c3962015-09-14 10:57:35 -07001738 audio_usecase_t ret_uc = USECASE_INVALID;
1739 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001740 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001741 if (!adev->multi_offload_enable) {
1742 if (is_direct_pcm)
1743 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1744 else
1745 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001746
vivek mehta446c3962015-09-14 10:57:35 -07001747 pthread_mutex_lock(&adev->lock);
1748 if (get_usecase_from_list(adev, ret_uc) != NULL)
1749 ret_uc = USECASE_INVALID;
1750 pthread_mutex_unlock(&adev->lock);
1751
1752 return ret_uc;
1753 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001754
1755 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001756 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1757 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1758 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1759 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001760 break;
1761 }
1762 }
vivek mehta446c3962015-09-14 10:57:35 -07001763
1764 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1765 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001766}
1767
1768static void free_offload_usecase(struct audio_device *adev,
1769 audio_usecase_t uc_id)
1770{
vivek mehta446c3962015-09-14 10:57:35 -07001771 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001772 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001773
1774 if (!adev->multi_offload_enable)
1775 return;
1776
1777 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1778 if (offload_usecases[offload_uc_index] == uc_id) {
1779 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001780 break;
1781 }
1782 }
1783 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1784}
1785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786static void *offload_thread_loop(void *context)
1787{
1788 struct stream_out *out = (struct stream_out *) context;
1789 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001790 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1793 set_sched_policy(0, SP_FOREGROUND);
1794 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1795
1796 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001797 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 for (;;) {
1799 struct offload_cmd *cmd = NULL;
1800 stream_callback_event_t event;
1801 bool send_callback = false;
1802
1803 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1804 __func__, list_empty(&out->offload_cmd_list),
1805 out->offload_state);
1806 if (list_empty(&out->offload_cmd_list)) {
1807 ALOGV("%s SLEEPING", __func__);
1808 pthread_cond_wait(&out->offload_cond, &out->lock);
1809 ALOGV("%s RUNNING", __func__);
1810 continue;
1811 }
1812
1813 item = list_head(&out->offload_cmd_list);
1814 cmd = node_to_item(item, struct offload_cmd, node);
1815 list_remove(item);
1816
1817 ALOGVV("%s STATE %d CMD %d out->compr %p",
1818 __func__, out->offload_state, cmd->cmd, out->compr);
1819
1820 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1821 free(cmd);
1822 break;
1823 }
1824
1825 if (out->compr == NULL) {
1826 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001827 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828 pthread_cond_signal(&out->cond);
1829 continue;
1830 }
1831 out->offload_thread_blocked = true;
1832 pthread_mutex_unlock(&out->lock);
1833 send_callback = false;
1834 switch(cmd->cmd) {
1835 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001836 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001838 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 send_callback = true;
1840 event = STREAM_CBK_EVENT_WRITE_READY;
1841 break;
1842 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001843 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301844 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001845 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301846 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001847 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301848 if (ret < 0)
1849 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301850 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301851 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001852 compress_drain(out->compr);
1853 else
1854 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301855 if (ret != -ENETRESET) {
1856 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301857 pthread_mutex_lock(&out->lock);
1858 out->send_new_metadata = 1;
1859 out->send_next_track_params = true;
1860 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301861 event = STREAM_CBK_EVENT_DRAIN_READY;
1862 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1863 } else
1864 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 break;
1866 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001867 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001869 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 send_callback = true;
1871 event = STREAM_CBK_EVENT_DRAIN_READY;
1872 break;
1873 default:
1874 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1875 break;
1876 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001877 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 out->offload_thread_blocked = false;
1879 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001880 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001881 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001882 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001883 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 free(cmd);
1885 }
1886
1887 pthread_cond_signal(&out->cond);
1888 while (!list_empty(&out->offload_cmd_list)) {
1889 item = list_head(&out->offload_cmd_list);
1890 list_remove(item);
1891 free(node_to_item(item, struct offload_cmd, node));
1892 }
1893 pthread_mutex_unlock(&out->lock);
1894
1895 return NULL;
1896}
1897
1898static int create_offload_callback_thread(struct stream_out *out)
1899{
1900 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1901 list_init(&out->offload_cmd_list);
1902 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1903 offload_thread_loop, out);
1904 return 0;
1905}
1906
1907static int destroy_offload_callback_thread(struct stream_out *out)
1908{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001909 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001910 stop_compressed_output_l(out);
1911 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1912
1913 pthread_mutex_unlock(&out->lock);
1914 pthread_join(out->offload_thread, (void **) NULL);
1915 pthread_cond_destroy(&out->offload_cond);
1916
1917 return 0;
1918}
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int stop_output_stream(struct stream_out *out)
1921{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301922 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 struct audio_usecase *uc_info;
1924 struct audio_device *adev = out->dev;
1925
Eric Laurent994a6932013-07-17 11:51:42 -07001926 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 uc_info = get_usecase_from_list(adev, out->usecase);
1929 if (uc_info == NULL) {
1930 ALOGE("%s: Could not find the usecase (%d) in the list",
1931 __func__, out->usecase);
1932 return -EINVAL;
1933 }
1934
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001935 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301936 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001937 if (adev->visualizer_stop_output != NULL)
1938 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001939
1940 audio_extn_dts_remove_state_notifier_node(out->usecase);
1941
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001942 if (adev->offload_effects_stop_output != NULL)
1943 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1944 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001945
Eric Laurent150dbfe2013-02-27 14:31:02 -08001946 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001947 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948
1949 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001950 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001952 list_remove(&uc_info->list);
1953 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001955 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301956 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001957 ALOGV("Disable passthrough , reset mixer to pcm");
1958 /* NO_PASSTHROUGH */
1959 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001960 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001961 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1962 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001963
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301964 /* Must be called after removing the usecase from list */
1965 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301966 audio_extn_keep_alive_start();
1967
Eric Laurent994a6932013-07-17 11:51:42 -07001968 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 return ret;
1970}
1971
1972int start_output_stream(struct stream_out *out)
1973{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 struct audio_usecase *uc_info;
1976 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301977 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001979 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1980 ret = -EINVAL;
1981 goto error_config;
1982 }
1983
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301984 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1985 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1986 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301987
Naresh Tanniru80659832014-06-04 18:17:56 +05301988 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301989 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301990 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301991 goto error_config;
1992 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301993
Eric Laurentb23d5282013-05-14 15:27:20 -07001994 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 if (out->pcm_device_id < 0) {
1996 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1997 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001998 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001999 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 }
2001
2002 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002003
2004 if (!uc_info) {
2005 ret = -ENOMEM;
2006 goto error_config;
2007 }
2008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 uc_info->id = out->usecase;
2010 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002011 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002012 uc_info->devices = out->devices;
2013 uc_info->in_snd_device = SND_DEVICE_NONE;
2014 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002015 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302017 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2018 adev->perf_lock_opts,
2019 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302020
2021 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2022 audio_extn_keep_alive_stop();
2023 if (audio_extn_passthru_is_enabled() &&
2024 audio_extn_passthru_is_passthrough_stream(out)) {
2025 audio_extn_passthru_on_start(out);
2026 audio_extn_passthru_update_stream_configuration(adev, out);
2027 }
2028 }
2029
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002030 select_devices(adev, out->usecase);
2031
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002032 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2033 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002034 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002035 unsigned int flags = PCM_OUT;
2036 unsigned int pcm_open_retry_count = 0;
2037 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2038 flags |= PCM_MMAP | PCM_NOIRQ;
2039 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002040 } else if (out->realtime) {
2041 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002042 } else
2043 flags |= PCM_MONOTONIC;
2044
2045 while (1) {
2046 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2047 flags, &out->config);
2048 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2049 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2050 if (out->pcm != NULL) {
2051 pcm_close(out->pcm);
2052 out->pcm = NULL;
2053 }
2054 if (pcm_open_retry_count-- == 0) {
2055 ret = -EIO;
2056 goto error_open;
2057 }
2058 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2059 continue;
2060 }
2061 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002063
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002064 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2065 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002066
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002067 ALOGV("%s: pcm_prepare", __func__);
2068 if (pcm_is_ready(out->pcm)) {
2069 ret = pcm_prepare(out->pcm);
2070 if (ret < 0) {
2071 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2072 pcm_close(out->pcm);
2073 out->pcm = NULL;
2074 goto error_open;
2075 }
2076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002078 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2079 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002081 out->compr = compress_open(adev->snd_card,
2082 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 COMPRESS_IN, &out->compr_config);
2084 if (out->compr && !is_compress_ready(out->compr)) {
2085 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2086 compress_close(out->compr);
2087 out->compr = NULL;
2088 ret = -EIO;
2089 goto error_open;
2090 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302091 /* compress_open sends params of the track, so reset the flag here */
2092 out->is_compr_metadata_avail = false;
2093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 if (out->offload_callback)
2095 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002096
Fred Oh3f43e742015-03-04 18:42:34 -08002097 /* Since small bufs uses blocking writes, a write will be blocked
2098 for the default max poll time (20s) in the event of an SSR.
2099 Reduce the poll time to observe and deal with SSR faster.
2100 */
Ashish Jain5106d362016-05-11 19:23:33 +05302101 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002102 compress_set_max_poll_wait(out->compr, 1000);
2103 }
2104
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002105 audio_extn_dts_create_state_notifier_node(out->usecase);
2106 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2107 popcount(out->channel_mask),
2108 out->playback_started);
2109
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002110#ifdef DS1_DOLBY_DDP_ENABLED
2111 if (audio_extn_is_dolby_format(out->format))
2112 audio_extn_dolby_send_ddp_endp_params(adev);
2113#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302114 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002115 if (adev->visualizer_start_output != NULL)
2116 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2117 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302118 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002119 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002122
2123 if (ret == 0) {
2124 register_out_stream(out);
2125 if (out->realtime) {
2126 ret = pcm_start(out->pcm);
2127 if (ret < 0)
2128 goto error_open;
2129 }
2130 }
2131
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302132 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002133 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002134
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002135 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302137 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002139error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302140 /*
2141 * sleep 50ms to allow sufficient time for kernel
2142 * drivers to recover incases like SSR.
2143 */
2144 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146}
2147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148static int check_input_parameters(uint32_t sample_rate,
2149 audio_format_t format,
2150 int channel_count)
2151{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002152 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302154 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2155 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2156 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002157 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302158 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002159
2160 switch (channel_count) {
2161 case 1:
2162 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302163 case 3:
2164 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002165 case 6:
2166 break;
2167 default:
2168 ret = -EINVAL;
2169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170
2171 switch (sample_rate) {
2172 case 8000:
2173 case 11025:
2174 case 12000:
2175 case 16000:
2176 case 22050:
2177 case 24000:
2178 case 32000:
2179 case 44100:
2180 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302181 case 96000:
2182 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 break;
2184 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002185 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 }
2187
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189}
2190
2191static size_t get_input_buffer_size(uint32_t sample_rate,
2192 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002193 int channel_count,
2194 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195{
2196 size_t size = 0;
2197
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002198 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2199 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002201 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002202 if (is_low_latency)
2203 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302204
2205 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002207 /* make sure the size is multiple of 32 bytes
2208 * At 48 kHz mono 16-bit PCM:
2209 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2210 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2211 */
2212 size += 0x1f;
2213 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002214
2215 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216}
2217
Ashish Jain058165c2016-09-28 23:18:48 +05302218static size_t get_output_period_size(uint32_t sample_rate,
2219 audio_format_t format,
2220 int channel_count,
2221 int duration /*in millisecs*/)
2222{
2223 size_t size = 0;
2224 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2225
2226 if ((duration == 0) || (sample_rate == 0) ||
2227 (bytes_per_sample == 0) || (channel_count == 0)) {
2228 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2229 bytes_per_sample, channel_count);
2230 return -EINVAL;
2231 }
2232
2233 size = (sample_rate *
2234 duration *
2235 bytes_per_sample *
2236 channel_count) / 1000;
2237 /*
2238 * To have same PCM samples for all channels, the buffer size requires to
2239 * be multiple of (number of channels * bytes per sample)
2240 * For writes to succeed, the buffer must be written at address which is multiple of 32
2241 */
2242 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2243
2244 return (size/(channel_count * bytes_per_sample));
2245}
2246
Ashish Jain5106d362016-05-11 19:23:33 +05302247static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2248{
2249 uint64_t actual_frames_rendered = 0;
2250 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2251
2252 /* This adjustment accounts for buffering after app processor.
2253 * It is based on estimated DSP latency per use case, rather than exact.
2254 */
2255 int64_t platform_latency = platform_render_latency(out->usecase) *
2256 out->sample_rate / 1000000LL;
2257
2258 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2259 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2260 * hence only estimate.
2261 */
2262 int64_t signed_frames = out->written - kernel_buffer_size;
2263
2264 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2265
2266 if (signed_frames > 0)
2267 actual_frames_rendered = signed_frames;
2268
2269 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2270 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2271 (long long int)out->written, (int)kernel_buffer_size,
2272 audio_bytes_per_sample(out->compr_config.codec->format),
2273 popcount(out->channel_mask));
2274
2275 return actual_frames_rendered;
2276}
2277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2279{
2280 struct stream_out *out = (struct stream_out *)stream;
2281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283}
2284
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002285static int out_set_sample_rate(struct audio_stream *stream __unused,
2286 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287{
2288 return -ENOSYS;
2289}
2290
2291static size_t out_get_buffer_size(const struct audio_stream *stream)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002295 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002297 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2298 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302299 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302300 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002302 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002303 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304}
2305
2306static uint32_t out_get_channels(const struct audio_stream *stream)
2307{
2308 struct stream_out *out = (struct stream_out *)stream;
2309
2310 return out->channel_mask;
2311}
2312
2313static audio_format_t out_get_format(const struct audio_stream *stream)
2314{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 struct stream_out *out = (struct stream_out *)stream;
2316
2317 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318}
2319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320static int out_set_format(struct audio_stream *stream __unused,
2321 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322{
2323 return -ENOSYS;
2324}
2325
2326static int out_standby(struct audio_stream *stream)
2327{
2328 struct stream_out *out = (struct stream_out *)stream;
2329 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302331 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2332 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002334 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002336 if (adev->adm_deregister_stream)
2337 adev->adm_deregister_stream(adev->adm_data, out->handle);
2338
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002339 if (is_offload_usecase(out->usecase))
2340 stop_compressed_output_l(out);
2341
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002342 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002344 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2345 voice_extn_compress_voip_close_output_stream(stream);
2346 pthread_mutex_unlock(&adev->lock);
2347 pthread_mutex_unlock(&out->lock);
2348 ALOGD("VOIP output entered standby");
2349 return 0;
2350 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 if (out->pcm) {
2352 pcm_close(out->pcm);
2353 out->pcm = NULL;
2354 }
2355 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002356 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302357 out->send_next_track_params = false;
2358 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002359 out->gapless_mdata.encoder_delay = 0;
2360 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 if (out->compr != NULL) {
2362 compress_close(out->compr);
2363 out->compr = NULL;
2364 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002365 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002367 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 }
2369 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302370 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 return 0;
2372}
2373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002374static int out_dump(const struct audio_stream *stream __unused,
2375 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376{
2377 return 0;
2378}
2379
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002380static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2381{
2382 int ret = 0;
2383 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002384
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002385 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002386 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002387 return -EINVAL;
2388 }
2389
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302390 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002391
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002392 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2393 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302394 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002395 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002396 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2397 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302398 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002399 }
2400
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002401 ALOGV("%s new encoder delay %u and padding %u", __func__,
2402 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2403
2404 return 0;
2405}
2406
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002407static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2408{
2409 return out == adev->primary_output || out == adev->voice_tx_output;
2410}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2413{
2414 struct stream_out *out = (struct stream_out *)stream;
2415 struct audio_device *adev = out->dev;
2416 struct str_parms *parms;
2417 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002418 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419
sangwoobc677242013-08-08 16:53:43 +09002420 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002421 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302423 if (!parms)
2424 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002425 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2426 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002428 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002429 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002432 * When HDMI cable is unplugged the music playback is paused and
2433 * the policy manager sends routing=0. But the audioflinger continues
2434 * to write data until standby time (3sec). As the HDMI core is
2435 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002436 * Avoid this by routing audio to speaker until standby.
2437 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002438 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2439 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302440 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002441 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2442 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302444 /*
2445 * When A2DP is disconnected the
2446 * music playback is paused and the policy manager sends routing=0
2447 * But the audioflingercontinues to write data until standby time
2448 * (3sec). As BT is turned off, the write gets blocked.
2449 * Avoid this by routing audio to speaker until standby.
2450 */
2451 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2452 (val == AUDIO_DEVICE_NONE)) {
2453 val = AUDIO_DEVICE_OUT_SPEAKER;
2454 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002455
2456 /*
2457 * select_devices() call below switches all the usecases on the same
2458 * backend to the new device. Refer to check_usecases_codec_backend() in
2459 * the select_devices(). But how do we undo this?
2460 *
2461 * For example, music playback is active on headset (deep-buffer usecase)
2462 * and if we go to ringtones and select a ringtone, low-latency usecase
2463 * will be started on headset+speaker. As we can't enable headset+speaker
2464 * and headset devices at the same time, select_devices() switches the music
2465 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2466 * So when the ringtone playback is completed, how do we undo the same?
2467 *
2468 * We are relying on the out_set_parameters() call on deep-buffer output,
2469 * once the ringtone playback is ended.
2470 * NOTE: We should not check if the current devices are same as new devices.
2471 * Because select_devices() must be called to switch back the music
2472 * playback to headset.
2473 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002474 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002475 audio_devices_t new_dev = val;
2476 bool same_dev = out->devices == new_dev;
2477 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002478
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002479 if (output_drives_call(adev, out)) {
2480 if(!voice_is_in_call(adev)) {
2481 if (adev->mode == AUDIO_MODE_IN_CALL) {
2482 adev->current_call_output = out;
2483 ret = voice_start_call(adev);
2484 }
2485 } else {
2486 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002487 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002488 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002489 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002490
2491 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002492 if (!same_dev) {
2493 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302494 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2495 adev->perf_lock_opts,
2496 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002497 if (adev->adm_on_routing_change)
2498 adev->adm_on_routing_change(adev->adm_data,
2499 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002500 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002501 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302502 if (!same_dev)
2503 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002504 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002505 }
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002508 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002510
2511 if (out == adev->primary_output) {
2512 pthread_mutex_lock(&adev->lock);
2513 audio_extn_set_parameters(adev, parms);
2514 pthread_mutex_unlock(&adev->lock);
2515 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002516 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002517 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002519
2520 audio_extn_dts_create_state_notifier_node(out->usecase);
2521 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2522 popcount(out->channel_mask),
2523 out->playback_started);
2524
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002525 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002526 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302529error:
Eric Laurent994a6932013-07-17 11:51:42 -07002530 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 return ret;
2532}
2533
2534static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2535{
2536 struct stream_out *out = (struct stream_out *)stream;
2537 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002538 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 char value[256];
2540 struct str_parms *reply = str_parms_create();
2541 size_t i, j;
2542 int ret;
2543 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002544
2545 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002546 if (reply) {
2547 str_parms_destroy(reply);
2548 }
2549 if (query) {
2550 str_parms_destroy(query);
2551 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002552 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2553 return NULL;
2554 }
2555
Eric Laurent994a6932013-07-17 11:51:42 -07002556 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2558 if (ret >= 0) {
2559 value[0] = '\0';
2560 i = 0;
2561 while (out->supported_channel_masks[i] != 0) {
2562 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2563 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2564 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002565 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002567 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 first = false;
2569 break;
2570 }
2571 }
2572 i++;
2573 }
2574 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2575 str = str_parms_to_str(reply);
2576 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 voice_extn_out_get_parameters(out, query, reply);
2578 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002579 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002580 free(str);
2581 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002584
Alexy Joseph62142aa2015-11-16 15:10:34 -08002585
2586 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2587 if (ret >= 0) {
2588 value[0] = '\0';
2589 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2590 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302591 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002592 } else {
2593 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302594 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002595 }
2596 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002597 if (str)
2598 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002599 str = str_parms_to_str(reply);
2600 }
2601
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002602 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2603 if (ret >= 0) {
2604 value[0] = '\0';
2605 i = 0;
2606 first = true;
2607 while (out->supported_formats[i] != 0) {
2608 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2609 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2610 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002611 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002612 }
2613 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2614 first = false;
2615 break;
2616 }
2617 }
2618 i++;
2619 }
2620 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002621 if (str)
2622 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002623 str = str_parms_to_str(reply);
2624 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002625
2626 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2627 if (ret >= 0) {
2628 value[0] = '\0';
2629 i = 0;
2630 first = true;
2631 while (out->supported_sample_rates[i] != 0) {
2632 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2633 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2634 if (!first) {
2635 strlcat(value, "|", sizeof(value));
2636 }
2637 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2638 first = false;
2639 break;
2640 }
2641 }
2642 i++;
2643 }
2644 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2645 if (str)
2646 free(str);
2647 str = str_parms_to_str(reply);
2648 }
2649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 str_parms_destroy(query);
2651 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002652 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 return str;
2654}
2655
2656static uint32_t out_get_latency(const struct audio_stream_out *stream)
2657{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002658 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002660 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661
Alexy Josephaa54c872014-12-03 02:46:47 -08002662 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002663 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002664 } else if (out->realtime) {
2665 // since the buffer won't be filled up faster than realtime,
2666 // return a smaller number
2667 if (out->config.rate)
2668 period_ms = (out->af_period_multiplier * out->config.period_size *
2669 1000) / (out->config.rate);
2670 else
2671 period_ms = 0;
2672 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002673 } else {
2674 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002675 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002676 }
2677
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302678 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002679 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680}
2681
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302682static float AmpToDb(float amplification)
2683{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302684 float db = DSD_VOLUME_MIN_DB;
2685 if (amplification > 0) {
2686 db = 20 * log10(amplification);
2687 if(db < DSD_VOLUME_MIN_DB)
2688 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302689 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302690 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302691}
2692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693static int out_set_volume(struct audio_stream_out *stream, float left,
2694 float right)
2695{
Eric Laurenta9024de2013-04-04 09:19:12 -07002696 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002697 int volume[2];
2698
Eric Laurenta9024de2013-04-04 09:19:12 -07002699 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2700 /* only take left channel into account: the API is for stereo anyway */
2701 out->muted = (left == 0.0f);
2702 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002703 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302704 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002705 /*
2706 * Set mute or umute on HDMI passthrough stream.
2707 * Only take left channel into account.
2708 * Mute is 0 and unmute 1
2709 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302710 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302711 } else if (out->format == AUDIO_FORMAT_DSD){
2712 char mixer_ctl_name[128] = "DSD Volume";
2713 struct audio_device *adev = out->dev;
2714 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2715
2716 if (!ctl) {
2717 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2718 __func__, mixer_ctl_name);
2719 return -EINVAL;
2720 }
2721 volume[0] = (int)(AmpToDb(left));
2722 volume[1] = (int)(AmpToDb(right));
2723 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2724 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002725 } else {
2726 char mixer_ctl_name[128];
2727 struct audio_device *adev = out->dev;
2728 struct mixer_ctl *ctl;
2729 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002730 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002732 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2733 "Compress Playback %d Volume", pcm_device_id);
2734 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2735 if (!ctl) {
2736 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2737 __func__, mixer_ctl_name);
2738 return -EINVAL;
2739 }
2740 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2741 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2742 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2743 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002745 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 return -ENOSYS;
2748}
2749
2750static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2751 size_t bytes)
2752{
2753 struct stream_out *out = (struct stream_out *)stream;
2754 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302755 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002756 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002758 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302759
Naresh Tanniru80659832014-06-04 18:17:56 +05302760 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002761
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302762 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302763 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302764 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2765 pthread_mutex_unlock(&out->lock);
2766 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302767 } else {
2768 /* increase written size during SSR to avoid mismatch
2769 * with the written frames count in AF
2770 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002771 // bytes per frame
2772 size_t bpf = audio_bytes_per_sample(out->format) *
2773 audio_channel_count_from_out_mask(out->channel_mask);
2774 if (bpf != 0)
2775 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302776 ALOGD(" %s: sound card is not active/SSR state", __func__);
2777 ret= -EIO;
2778 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302779 }
2780 }
2781
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302782 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302783 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2784 if (audio_bytes_per_sample(out->format) != 0)
2785 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2786 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302787 goto exit;
2788 }
2789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002791 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002792 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002793 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2794 ret = voice_extn_compress_voip_start_output_stream(out);
2795 else
2796 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002797 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002800 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 goto exit;
2802 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002803
2804 if (last_known_cal_step != -1) {
2805 ALOGD("%s: retry previous failed cal level set", __func__);
2806 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2807 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809
Ashish Jain81eb2a82015-05-13 10:52:34 +05302810 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002811 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302812 adev->is_channel_status_set = true;
2813 }
2814
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002815 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002816 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002817 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002818 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002819 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2820 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302821 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2822 ALOGD("copl(%p):send next track params in gapless", out);
2823 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2824 out->send_next_track_params = false;
2825 out->is_compr_metadata_avail = false;
2826 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002827 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302828 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302829 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002830
Ashish Jain83a6cc22016-06-28 14:34:17 +05302831 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302832 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302833 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302834 pthread_mutex_unlock(&out->lock);
2835 return -EINVAL;
2836 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302837 audio_format_t dst_format = out->hal_op_format;
2838 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302839
2840 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2841 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2842
Ashish Jain83a6cc22016-06-28 14:34:17 +05302843 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302844 dst_format,
2845 buffer,
2846 src_format,
2847 frames);
2848
Ashish Jain83a6cc22016-06-28 14:34:17 +05302849 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302850 bytes_to_write);
2851
2852 /*Convert written bytes in audio flinger format*/
2853 if (ret > 0)
2854 ret = ((ret * format_to_bitwidth_table[out->format]) /
2855 format_to_bitwidth_table[dst_format]);
2856 }
2857 } else
2858 ret = compress_write(out->compr, buffer, bytes);
2859
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302860 if (ret < 0)
2861 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302862 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302863 /*msg to cb thread only if non blocking write is enabled*/
2864 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302865 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302867 } else if (-ENETRESET == ret) {
2868 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2869 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2870 pthread_mutex_unlock(&out->lock);
2871 out_standby(&out->stream.common);
2872 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 }
Ashish Jain5106d362016-05-11 19:23:33 +05302874 if ( ret == (ssize_t)bytes && !out->non_blocking)
2875 out->written += bytes;
2876
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302877 /* Call compr start only when non-zero bytes of data is there to be rendered */
2878 if (!out->playback_started && ret > 0) {
2879 int status = compress_start(out->compr);
2880 if (status < 0) {
2881 ret = status;
2882 ALOGE("%s: compr start failed with err %d", __func__, errno);
2883 goto exit;
2884 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002885 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->playback_started = 1;
2887 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002888
2889 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2890 popcount(out->channel_mask),
2891 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 }
2893 pthread_mutex_unlock(&out->lock);
2894 return ret;
2895 } else {
2896 if (out->pcm) {
2897 if (out->muted)
2898 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002899
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302900 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002901
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002902 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002903
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002904 if (out->config.rate)
2905 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2906 out->config.rate;
2907
2908 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2909
2910 request_out_focus(out, ns);
2911
2912 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002913 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002914 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302915 out->convert_buffer != NULL) {
2916
2917 memcpy_by_audio_format(out->convert_buffer,
2918 out->hal_op_format,
2919 buffer,
2920 out->hal_ip_format,
2921 out->config.period_size * out->config.channels);
2922
2923 ret = pcm_write(out->pcm, out->convert_buffer,
2924 (out->config.period_size *
2925 out->config.channels *
2926 format_to_bitwidth_table[out->hal_op_format]));
2927 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002928 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302929 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002930
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002931 release_out_focus(out);
2932
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302933 if (ret < 0)
2934 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302935 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2936 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2937 else
2938 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 }
2941
2942exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302943 /* ToDo: There may be a corner case when SSR happens back to back during
2944 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302945 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302946 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302947 }
2948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949 pthread_mutex_unlock(&out->lock);
2950
2951 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002952 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002953 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302954 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302955 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302956 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302957 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302958 out->standby = true;
2959 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302961 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2962 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2963 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 }
2965 return bytes;
2966}
2967
2968static int out_get_render_position(const struct audio_stream_out *stream,
2969 uint32_t *dsp_frames)
2970{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302972 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002973
2974 if (dsp_frames == NULL)
2975 return -EINVAL;
2976
2977 *dsp_frames = 0;
2978 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002979 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302980
2981 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2982 * this operation and adev_close_output_stream(where out gets reset).
2983 */
2984 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2985 *dsp_frames = get_actual_pcm_frames_rendered(out);
2986 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2987 return 0;
2988 }
2989
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002990 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302991 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302992 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002993 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302994 if (ret < 0)
2995 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302997 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 }
2999 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303000 if (-ENETRESET == ret) {
3001 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3002 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3003 return -EINVAL;
3004 } else if(ret < 0) {
3005 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3006 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303007 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3008 /*
3009 * Handle corner case where compress session is closed during SSR
3010 * and timestamp is queried
3011 */
3012 ALOGE(" ERROR: sound card not active, return error");
3013 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303014 } else {
3015 return 0;
3016 }
Zhou Song32a556e2015-05-05 10:46:56 +08003017 } else if (audio_is_linear_pcm(out->format)) {
3018 *dsp_frames = out->written;
3019 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 } else
3021 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022}
3023
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003024static int out_add_audio_effect(const struct audio_stream *stream __unused,
3025 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026{
3027 return 0;
3028}
3029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003030static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3031 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032{
3033 return 0;
3034}
3035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003036static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3037 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038{
3039 return -EINVAL;
3040}
3041
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042static int out_get_presentation_position(const struct audio_stream_out *stream,
3043 uint64_t *frames, struct timespec *timestamp)
3044{
3045 struct stream_out *out = (struct stream_out *)stream;
3046 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003047 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003048
Ashish Jain5106d362016-05-11 19:23:33 +05303049 /* below piece of code is not guarded against any lock because audioFliner serializes
3050 * this operation and adev_close_output_stream( where out gets reset).
3051 */
3052 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3053 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3054 *frames = get_actual_pcm_frames_rendered(out);
3055 /* this is the best we can do */
3056 clock_gettime(CLOCK_MONOTONIC, timestamp);
3057 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3058 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3059 return 0;
3060 }
3061
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003062 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063
Ashish Jain5106d362016-05-11 19:23:33 +05303064 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3065 ret = compress_get_tstamp(out->compr, &dsp_frames,
3066 &out->sample_rate);
3067 ALOGVV("%s rendered frames %ld sample_rate %d",
3068 __func__, dsp_frames, out->sample_rate);
3069 *frames = dsp_frames;
3070 if (ret < 0)
3071 ret = -errno;
3072 if (-ENETRESET == ret) {
3073 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3074 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3075 ret = -EINVAL;
3076 } else
3077 ret = 0;
3078 /* this is the best we can do */
3079 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003080 } else {
3081 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003082 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003083 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3084 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003085 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003086 // This adjustment accounts for buffering after app processor.
3087 // It is based on estimated DSP latency per use case, rather than exact.
3088 signed_frames -=
3089 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3090
Eric Laurent949a0892013-09-20 09:20:13 -07003091 // It would be unusual for this value to be negative, but check just in case ...
3092 if (signed_frames >= 0) {
3093 *frames = signed_frames;
3094 ret = 0;
3095 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003096 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303097 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3098 *frames = out->written;
3099 clock_gettime(CLOCK_MONOTONIC, timestamp);
3100 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003101 }
3102 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003103 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003104 return ret;
3105}
3106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107static int out_set_callback(struct audio_stream_out *stream,
3108 stream_callback_t callback, void *cookie)
3109{
3110 struct stream_out *out = (struct stream_out *)stream;
3111
3112 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003113 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003114 out->offload_callback = callback;
3115 out->offload_cookie = cookie;
3116 pthread_mutex_unlock(&out->lock);
3117 return 0;
3118}
3119
3120static int out_pause(struct audio_stream_out* stream)
3121{
3122 struct stream_out *out = (struct stream_out *)stream;
3123 int status = -ENOSYS;
3124 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003126 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003127 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303129 struct audio_device *adev = out->dev;
3130 int snd_scard_state = get_snd_card_state(adev);
3131
3132 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3133 status = compress_pause(out->compr);
3134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003136
Mingming Yin21854652016-04-13 11:54:02 -07003137 if (audio_extn_passthru_is_active()) {
3138 ALOGV("offload use case, pause passthru");
3139 audio_extn_passthru_on_pause(out);
3140 }
3141
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303142 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003143 audio_extn_dts_notify_playback_state(out->usecase, 0,
3144 out->sample_rate, popcount(out->channel_mask),
3145 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 }
3147 pthread_mutex_unlock(&out->lock);
3148 }
3149 return status;
3150}
3151
3152static int out_resume(struct audio_stream_out* stream)
3153{
3154 struct stream_out *out = (struct stream_out *)stream;
3155 int status = -ENOSYS;
3156 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003157 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003158 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003160 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003161 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303162 struct audio_device *adev = out->dev;
3163 int snd_scard_state = get_snd_card_state(adev);
3164
Mingming Yin21854652016-04-13 11:54:02 -07003165 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3166 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3167 pthread_mutex_lock(&out->dev->lock);
3168 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003169 pthread_mutex_unlock(&out->dev->lock);
3170 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303171 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003172 }
3173 if (!status) {
3174 out->offload_state = OFFLOAD_STATE_PLAYING;
3175 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303176 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003177 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3178 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003179 }
3180 pthread_mutex_unlock(&out->lock);
3181 }
3182 return status;
3183}
3184
3185static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3186{
3187 struct stream_out *out = (struct stream_out *)stream;
3188 int status = -ENOSYS;
3189 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003190 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003191 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3193 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3194 else
3195 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3196 pthread_mutex_unlock(&out->lock);
3197 }
3198 return status;
3199}
3200
3201static int out_flush(struct audio_stream_out* stream)
3202{
3203 struct stream_out *out = (struct stream_out *)stream;
3204 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003205 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003206 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003207 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003208 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3209 stop_compressed_output_l(out);
3210 out->written = 0;
3211 } else {
3212 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3213 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003215 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216 return 0;
3217 }
3218 return -ENOSYS;
3219}
3220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221/** audio_stream_in implementation **/
3222static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3223{
3224 struct stream_in *in = (struct stream_in *)stream;
3225
3226 return in->config.rate;
3227}
3228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003229static int in_set_sample_rate(struct audio_stream *stream __unused,
3230 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231{
3232 return -ENOSYS;
3233}
3234
3235static size_t in_get_buffer_size(const struct audio_stream *stream)
3236{
3237 struct stream_in *in = (struct stream_in *)stream;
3238
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003239 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3240 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003241 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3242 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003243
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003244 return in->config.period_size * in->af_period_multiplier *
3245 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246}
3247
3248static uint32_t in_get_channels(const struct audio_stream *stream)
3249{
3250 struct stream_in *in = (struct stream_in *)stream;
3251
3252 return in->channel_mask;
3253}
3254
3255static audio_format_t in_get_format(const struct audio_stream *stream)
3256{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003257 struct stream_in *in = (struct stream_in *)stream;
3258
3259 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260}
3261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003262static int in_set_format(struct audio_stream *stream __unused,
3263 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264{
3265 return -ENOSYS;
3266}
3267
3268static int in_standby(struct audio_stream *stream)
3269{
3270 struct stream_in *in = (struct stream_in *)stream;
3271 struct audio_device *adev = in->dev;
3272 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303273 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3274 stream, in->usecase, use_case_table[in->usecase]);
3275
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003276 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003277 if (!in->standby && in->is_st_session) {
3278 ALOGD("%s: sound trigger pcm stop lab", __func__);
3279 audio_extn_sound_trigger_stop_lab(in);
3280 in->standby = 1;
3281 }
3282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003284 if (adev->adm_deregister_stream)
3285 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3286
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003287 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003289 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3290 voice_extn_compress_voip_close_input_stream(stream);
3291 ALOGD("VOIP input entered standby");
3292 } else {
3293 if (in->pcm) {
3294 pcm_close(in->pcm);
3295 in->pcm = NULL;
3296 }
3297 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003298 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003299 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 }
3301 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003302 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 return status;
3304}
3305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003306static int in_dump(const struct audio_stream *stream __unused,
3307 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308{
3309 return 0;
3310}
3311
3312static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3313{
3314 struct stream_in *in = (struct stream_in *)stream;
3315 struct audio_device *adev = in->dev;
3316 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003318 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303320 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 parms = str_parms_create_str(kvpairs);
3322
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303323 if (!parms)
3324 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003325 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003326 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003327
3328 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3329 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 val = atoi(value);
3331 /* no audio source uses val == 0 */
3332 if ((in->source != val) && (val != 0)) {
3333 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003334 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3335 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3336 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003337 (in->config.rate == 8000 || in->config.rate == 16000 ||
3338 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003339 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003340 err = voice_extn_compress_voip_open_input_stream(in);
3341 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003342 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003343 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003344 }
3345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 }
3347 }
3348
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003349 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3350 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003352 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 in->device = val;
3354 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003355 if (!in->standby && !in->is_st_session) {
3356 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003357 if (adev->adm_on_routing_change)
3358 adev->adm_on_routing_change(adev->adm_data,
3359 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003360 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 }
3363 }
3364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003366 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367
3368 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303369error:
Eric Laurent994a6932013-07-17 11:51:42 -07003370 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 return ret;
3372}
3373
3374static char* in_get_parameters(const struct audio_stream *stream,
3375 const char *keys)
3376{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003377 struct stream_in *in = (struct stream_in *)stream;
3378 struct str_parms *query = str_parms_create_str(keys);
3379 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003380 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003381
3382 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003383 if (reply) {
3384 str_parms_destroy(reply);
3385 }
3386 if (query) {
3387 str_parms_destroy(query);
3388 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003389 ALOGE("in_get_parameters: failed to create query or reply");
3390 return NULL;
3391 }
3392
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003393 ALOGV("%s: enter: keys - %s", __func__, keys);
3394
3395 voice_extn_in_get_parameters(in, query, reply);
3396
3397 str = str_parms_to_str(reply);
3398 str_parms_destroy(query);
3399 str_parms_destroy(reply);
3400
3401 ALOGV("%s: exit: returns - %s", __func__, str);
3402 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403}
3404
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003405static int in_set_gain(struct audio_stream_in *stream __unused,
3406 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
3408 return 0;
3409}
3410
3411static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3412 size_t bytes)
3413{
3414 struct stream_in *in = (struct stream_in *)stream;
3415 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303416 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303417 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303418 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003420 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303421
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003422 if (in->is_st_session) {
3423 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3424 /* Read from sound trigger HAL */
3425 audio_extn_sound_trigger_read(in, buffer, bytes);
3426 pthread_mutex_unlock(&in->lock);
3427 return bytes;
3428 }
3429
Ashish Jainbbce4322016-02-16 13:25:27 +05303430 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003431 ALOGD(" %s: sound card is not active/SSR state", __func__);
3432 ret= -EIO;;
3433 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303434 }
3435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003437 pthread_mutex_lock(&adev->lock);
3438 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3439 ret = voice_extn_compress_voip_start_input_stream(in);
3440 else
3441 ret = start_input_stream(in);
3442 pthread_mutex_unlock(&adev->lock);
3443 if (ret != 0) {
3444 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 }
3446 in->standby = 0;
3447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003449 // what's the duration requested by the client?
3450 long ns = 0;
3451
3452 if (in->config.rate)
3453 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3454 in->config.rate;
3455
3456 request_in_focus(in, ns);
3457 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303460 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003461 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303462 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003463 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003464 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003465 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303466 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003467 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303468 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3469 if (bytes % 4 == 0) {
3470 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3471 int_buf_stream = buffer;
3472 for (size_t itt=0; itt < bytes/4 ; itt++) {
3473 int_buf_stream[itt] >>= 8;
3474 }
3475 } else {
3476 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3477 ret = -EINVAL;
3478 goto exit;
3479 }
3480 } if (ret < 0) {
3481 ret = -errno;
3482 }
3483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 }
3485
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003486 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 /*
3489 * Instead of writing zeroes here, we could trust the hardware
3490 * to always provide zeroes when muted.
3491 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303492 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3493 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 memset(buffer, 0, bytes);
3495
3496exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303497 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303498 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003499 if (-ENETRESET == ret)
3500 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 pthread_mutex_unlock(&in->lock);
3503
3504 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303505 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303506 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303507 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303508 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303509 in->standby = true;
3510 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303511 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003513 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303514 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303515 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 }
3517 return bytes;
3518}
3519
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003520static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521{
3522 return 0;
3523}
3524
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003525static int add_remove_audio_effect(const struct audio_stream *stream,
3526 effect_handle_t effect,
3527 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003529 struct stream_in *in = (struct stream_in *)stream;
3530 int status = 0;
3531 effect_descriptor_t desc;
3532
3533 status = (*effect)->get_descriptor(effect, &desc);
3534 if (status != 0)
3535 return status;
3536
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003537 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003538 pthread_mutex_lock(&in->dev->lock);
3539 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3540 in->enable_aec != enable &&
3541 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3542 in->enable_aec = enable;
3543 if (!in->standby)
3544 select_devices(in->dev, in->usecase);
3545 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003546 if (in->enable_ns != enable &&
3547 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3548 in->enable_ns = enable;
3549 if (!in->standby)
3550 select_devices(in->dev, in->usecase);
3551 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003552 pthread_mutex_unlock(&in->dev->lock);
3553 pthread_mutex_unlock(&in->lock);
3554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 return 0;
3556}
3557
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003558static int in_add_audio_effect(const struct audio_stream *stream,
3559 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560{
Eric Laurent994a6932013-07-17 11:51:42 -07003561 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003562 return add_remove_audio_effect(stream, effect, true);
3563}
3564
3565static int in_remove_audio_effect(const struct audio_stream *stream,
3566 effect_handle_t effect)
3567{
Eric Laurent994a6932013-07-17 11:51:42 -07003568 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003569 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570}
3571
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303572int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 audio_io_handle_t handle,
3574 audio_devices_t devices,
3575 audio_output_flags_t flags,
3576 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003577 struct audio_stream_out **stream_out,
3578 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579{
3580 struct audio_device *adev = (struct audio_device *)dev;
3581 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303582 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003583 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303586
3587 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3588 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003589 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303590 return -EINVAL;
3591 }
3592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3594
Mingming Yin3a941d42016-02-17 18:08:05 -08003595 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3596 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303597 devices, flags, &out->stream);
3598
3599
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003600 if (!out) {
3601 return -ENOMEM;
3602 }
3603
Haynes Mathew George204045b2015-02-25 20:32:03 -08003604 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003605 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003606 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 if (devices == AUDIO_DEVICE_NONE)
3609 devices = AUDIO_DEVICE_OUT_SPEAKER;
3610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 out->flags = flags;
3612 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003613 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003614 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003615 out->sample_rate = config->sample_rate;
3616 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3617 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003618 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003619 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003620 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303621 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622
Mingming Yin3a941d42016-02-17 18:08:05 -08003623 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3624 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3625 pthread_mutex_lock(&adev->lock);
3626 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3627 ret = read_hdmi_sink_caps(out);
3628 pthread_mutex_unlock(&adev->lock);
3629 if (ret != 0) {
3630 if (ret == -ENOSYS) {
3631 /* ignore and go with default */
3632 ret = 0;
3633 } else {
3634 ALOGE("error reading hdmi sink caps");
3635 goto error_open;
3636 }
3637 }
3638 }
3639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003641 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303642 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3643 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003644 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3645 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3646
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003647 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003648 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3649 /*
3650 * Do not handle stereo output in Multi-channel cases
3651 * Stereo case is handled in normal playback path
3652 */
3653 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3654 ret = AUDIO_CHANNEL_OUT_STEREO;
3655 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003656
3657 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3658 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003659 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003660 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003661 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003662
3663 if (config->sample_rate == 0)
3664 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3665 if (config->channel_mask == 0)
3666 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003667 if (config->format == 0)
3668 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003669
3670 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003672 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3674 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003676 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003678 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3679 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003680 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003681 ret = voice_extn_compress_voip_open_output_stream(out);
3682 if (ret != 0) {
3683 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3684 __func__, ret);
3685 goto error_open;
3686 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003687 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3688 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3689
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3691 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3692 ALOGE("%s: Unsupported Offload information", __func__);
3693 ret = -EINVAL;
3694 goto error_open;
3695 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003696
Mingming Yin3a941d42016-02-17 18:08:05 -08003697 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003698 if(config->offload_info.format == 0)
3699 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003700 if (config->offload_info.sample_rate == 0)
3701 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003702 }
3703
Mingming Yin90310102013-11-13 16:57:00 -08003704 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303705 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003706 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003707 ret = -EINVAL;
3708 goto error_open;
3709 }
3710
3711 out->compr_config.codec = (struct snd_codec *)
3712 calloc(1, sizeof(struct snd_codec));
3713
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003714 if (!out->compr_config.codec) {
3715 ret = -ENOMEM;
3716 goto error_open;
3717 }
3718
vivek mehta0ea887a2015-08-26 14:01:20 -07003719 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303720 out->stream.pause = out_pause;
3721 out->stream.flush = out_flush;
3722 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003723 out->usecase = get_offload_usecase(adev, true);
3724 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003725 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003726 out->stream.set_callback = out_set_callback;
3727 out->stream.pause = out_pause;
3728 out->stream.resume = out_resume;
3729 out->stream.drain = out_drain;
3730 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003731 out->usecase = get_offload_usecase(adev, false);
3732 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003733 }
vivek mehta446c3962015-09-14 10:57:35 -07003734
3735 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003736 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3737 config->format == 0 && config->sample_rate == 0 &&
3738 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003739 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003740 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3741 } else {
3742 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3743 ret = -EEXIST;
3744 goto error_open;
3745 }
vivek mehta446c3962015-09-14 10:57:35 -07003746 }
3747
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748 if (config->offload_info.channel_mask)
3749 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003750 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003751 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003752 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003753 } else {
3754 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3755 ret = -EINVAL;
3756 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003757 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003758
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003759 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003760 out->sample_rate = config->offload_info.sample_rate;
3761
Mingming Yin3ee55c62014-08-04 14:23:35 -07003762 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003763
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303764 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3765 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3766 audio_extn_dolby_send_ddp_endp_params(adev);
3767 audio_extn_dolby_set_dmid(adev);
3768 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003770 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003771 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772 out->compr_config.codec->bit_rate =
3773 config->offload_info.bit_rate;
3774 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303775 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003776 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303777 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003778 /*TODO: Do we need to change it for passthrough */
3779 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003780
Manish Dewangana6fc5442015-08-24 20:30:31 +05303781 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3782 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3783 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3784 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303785
3786 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3787 AUDIO_FORMAT_PCM) {
3788
3789 /*Based on platform support, configure appropriate alsa format for corresponding
3790 *hal input format.
3791 */
3792 out->compr_config.codec->format = hal_format_to_alsa(
3793 config->offload_info.format);
3794
Ashish Jain83a6cc22016-06-28 14:34:17 +05303795 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303796 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303797 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303798
3799 /*for direct PCM playback populate bit_width based on selected alsa format as
3800 *hal input format and alsa format might differ based on platform support.
3801 */
3802 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303803 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303804
3805 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3806
3807 /* Check if alsa session is configured with the same format as HAL input format,
3808 * if not then derive correct fragment size needed to accomodate the
3809 * conversion of HAL input format to alsa format.
3810 */
3811 audio_extn_utils_update_direct_pcm_fragment_size(out);
3812
3813 /*if hal input and output fragment size is different this indicates HAL input format is
3814 *not same as the alsa format
3815 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303816 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303817 /*Allocate a buffer to convert input data to the alsa configured format.
3818 *size of convert buffer is equal to the size required to hold one fragment size
3819 *worth of pcm data, this is because flinger does not write more than fragment_size
3820 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303821 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3822 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303823 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3824 ret = -ENOMEM;
3825 goto error_open;
3826 }
3827 }
3828 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3829 out->compr_config.fragment_size =
3830 audio_extn_passthru_get_buffer_size(&config->offload_info);
3831 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3832 } else {
3833 out->compr_config.fragment_size =
3834 platform_get_compress_offload_buffer_size(&config->offload_info);
3835 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3836 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003837
Amit Shekhar6f461b12014-08-01 14:52:58 -07003838 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303839 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003840
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003841 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3842 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003843
Alexy Josephaa54c872014-12-03 02:46:47 -08003844
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003845 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303846 out->send_next_track_params = false;
3847 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003848 out->offload_state = OFFLOAD_STATE_IDLE;
3849 out->playback_started = 0;
3850
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003851 audio_extn_dts_create_state_notifier_node(out->usecase);
3852
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3854 __func__, config->offload_info.version,
3855 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303856
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303857 /* Check if DSD audio format is supported in codec
3858 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303859 */
3860
3861 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303862 (!platform_check_codec_dsd_support(adev->platform) ||
3863 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303864 ret = -EINVAL;
3865 goto error_open;
3866 }
3867
Ashish Jain5106d362016-05-11 19:23:33 +05303868 /* Disable gapless if any of the following is true
3869 * passthrough playback
3870 * AV playback
3871 * Direct PCM playback
3872 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303873 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303874 (config->format == AUDIO_FORMAT_DSD) ||
3875 config->offload_info.has_video ||
3876 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303877 check_and_set_gapless_mode(adev, false);
3878 } else
3879 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003880
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303881 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003882 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3883 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303884 if (config->format == AUDIO_FORMAT_DSD) {
3885 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3886 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3887 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003888
3889 create_offload_callback_thread(out);
3890
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003891 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303892 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003893 if (ret != 0) {
3894 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3895 __func__, ret);
3896 goto error_open;
3897 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003898 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3899 if (config->sample_rate == 0)
3900 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3901 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3902 config->sample_rate != 8000) {
3903 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3904 ret = -EINVAL;
3905 goto error_open;
3906 }
3907 out->sample_rate = config->sample_rate;
3908 out->config.rate = config->sample_rate;
3909 if (config->format == AUDIO_FORMAT_DEFAULT)
3910 config->format = AUDIO_FORMAT_PCM_16_BIT;
3911 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3912 config->format = AUDIO_FORMAT_PCM_16_BIT;
3913 ret = -EINVAL;
3914 goto error_open;
3915 }
3916 out->format = config->format;
3917 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3918 out->config = pcm_config_afe_proxy_playback;
3919 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003920 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05303921 unsigned int channels = 0;
3922 /*Update config params to default if not set by the caller*/
3923 if (config->sample_rate == 0)
3924 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3925 if (config->channel_mask == AUDIO_CHANNEL_NONE)
3926 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3927 if (config->format == AUDIO_FORMAT_DEFAULT)
3928 config->format = AUDIO_FORMAT_PCM_16_BIT;
3929
3930 channels = audio_channel_count_from_out_mask(out->channel_mask);
3931
Ashish Jain83a6cc22016-06-28 14:34:17 +05303932 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3933 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003934 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3935 out->flags);
3936 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303937 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3938 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3939 out->config = pcm_config_low_latency;
3940 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3941 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3942 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05303943 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
3944 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
3945 if (out->config.period_size <= 0) {
3946 ALOGE("Invalid configuration period size is not valid");
3947 ret = -EINVAL;
3948 goto error_open;
3949 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05303950 } else {
3951 /* primary path is the default path selected if no other outputs are available/suitable */
3952 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3953 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3954 }
3955 out->hal_ip_format = format = out->format;
3956 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3957 out->hal_op_format = pcm_format_to_hal(out->config.format);
3958 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3959 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003960 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05303961 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303962 if (out->hal_ip_format != out->hal_op_format) {
3963 uint32_t buffer_size = out->config.period_size *
3964 format_to_bitwidth_table[out->hal_op_format] *
3965 out->config.channels;
3966 out->convert_buffer = calloc(1, buffer_size);
3967 if (out->convert_buffer == NULL){
3968 ALOGE("Allocation failed for convert buffer for size %d",
3969 out->compr_config.fragment_size);
3970 ret = -ENOMEM;
3971 goto error_open;
3972 }
3973 ALOGD("Convert buffer allocated of size %d", buffer_size);
3974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975 }
3976
Ashish Jain83a6cc22016-06-28 14:34:17 +05303977 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3978 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3979
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003980 /* TODO remove this hardcoding and check why width is zero*/
3981 if (out->bit_width == 0)
3982 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003983 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3984 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003985 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303986 out->bit_width, out->channel_mask,
3987 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003988 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3989 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3990 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003991 if(adev->primary_output == NULL)
3992 adev->primary_output = out;
3993 else {
3994 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003995 ret = -EEXIST;
3996 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003997 }
3998 }
3999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000 /* Check if this usecase is already existing */
4001 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004002 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4003 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004006 ret = -EEXIST;
4007 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 }
4009 pthread_mutex_unlock(&adev->lock);
4010
4011 out->stream.common.get_sample_rate = out_get_sample_rate;
4012 out->stream.common.set_sample_rate = out_set_sample_rate;
4013 out->stream.common.get_buffer_size = out_get_buffer_size;
4014 out->stream.common.get_channels = out_get_channels;
4015 out->stream.common.get_format = out_get_format;
4016 out->stream.common.set_format = out_set_format;
4017 out->stream.common.standby = out_standby;
4018 out->stream.common.dump = out_dump;
4019 out->stream.common.set_parameters = out_set_parameters;
4020 out->stream.common.get_parameters = out_get_parameters;
4021 out->stream.common.add_audio_effect = out_add_audio_effect;
4022 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4023 out->stream.get_latency = out_get_latency;
4024 out->stream.set_volume = out_set_volume;
4025 out->stream.write = out_write;
4026 out->stream.get_render_position = out_get_render_position;
4027 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004028 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004030 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004031 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004032 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004033 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034
4035 config->format = out->stream.common.get_format(&out->stream.common);
4036 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4037 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4038
4039 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304040 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004041 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004042
4043 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4044 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4045 popcount(out->channel_mask), out->playback_started);
4046
Eric Laurent994a6932013-07-17 11:51:42 -07004047 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004049
4050error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304051 if (out->convert_buffer)
4052 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004053 free(out);
4054 *stream_out = NULL;
4055 ALOGD("%s: exit: ret %d", __func__, ret);
4056 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057}
4058
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304059void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 struct audio_stream_out *stream)
4061{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 struct stream_out *out = (struct stream_out *)stream;
4063 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004064 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304066 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4067
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004068 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304069 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004070 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304071 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004072 if(ret != 0)
4073 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4074 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004075 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004076 out_standby(&stream->common);
4077
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004078 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004079 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004081 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004082 if (out->compr_config.codec != NULL)
4083 free(out->compr_config.codec);
4084 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004085
Ashish Jain83a6cc22016-06-28 14:34:17 +05304086 if (out->convert_buffer != NULL) {
4087 free(out->convert_buffer);
4088 out->convert_buffer = NULL;
4089 }
4090
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004091 if (adev->voice_tx_output == out)
4092 adev->voice_tx_output = NULL;
4093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004094 pthread_cond_destroy(&out->cond);
4095 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004097 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098}
4099
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004100static void close_compress_sessions(struct audio_device *adev)
4101{
Mingming Yin7b762e72015-03-04 13:47:32 -08004102 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304103 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004104 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004105 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304106
4107 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004108 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304109 if (is_offload_usecase(usecase->id)) {
4110 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004111 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4112 out = usecase->stream.out;
4113 pthread_mutex_unlock(&adev->lock);
4114 out_standby(&out->stream.common);
4115 pthread_mutex_lock(&adev->lock);
4116 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304117 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004118 }
4119 pthread_mutex_unlock(&adev->lock);
4120}
4121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4123{
4124 struct audio_device *adev = (struct audio_device *)dev;
4125 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004127 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004128 int ret;
4129 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004131 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304134 if (!parms)
4135 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004136 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4137 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304138 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304139 if (strstr(snd_card_status, "OFFLINE")) {
4140 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304141 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004142 //close compress sessions on OFFLINE status
4143 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304144 } else if (strstr(snd_card_status, "ONLINE")) {
4145 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304146 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004147 //send dts hpx license if enabled
4148 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304149 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304150 }
4151
4152 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004153 status = voice_set_parameters(adev, parms);
4154 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004155 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004157 status = platform_set_parameters(adev->platform, parms);
4158 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004159 goto done;
4160
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004161 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4162 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004163 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4165 adev->bluetooth_nrec = true;
4166 else
4167 adev->bluetooth_nrec = false;
4168 }
4169
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004170 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4171 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4173 adev->screen_off = false;
4174 else
4175 adev->screen_off = true;
4176 }
4177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004178 ret = str_parms_get_int(parms, "rotation", &val);
4179 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004180 bool reverse_speakers = false;
4181 switch(val) {
4182 // FIXME: note that the code below assumes that the speakers are in the correct placement
4183 // relative to the user when the device is rotated 90deg from its default rotation. This
4184 // assumption is device-specific, not platform-specific like this code.
4185 case 270:
4186 reverse_speakers = true;
4187 break;
4188 case 0:
4189 case 90:
4190 case 180:
4191 break;
4192 default:
4193 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004194 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004195 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004196 if (status == 0) {
4197 if (adev->speaker_lr_swap != reverse_speakers) {
4198 adev->speaker_lr_swap = reverse_speakers;
4199 // only update the selected device if there is active pcm playback
4200 struct audio_usecase *usecase;
4201 struct listnode *node;
4202 list_for_each(node, &adev->usecase_list) {
4203 usecase = node_to_item(node, struct audio_usecase, list);
4204 if (usecase->type == PCM_PLAYBACK) {
4205 select_devices(adev, usecase->id);
4206 break;
4207 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004208 }
4209 }
4210 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004211 }
4212
Mingming Yin514a8bc2014-07-29 15:22:21 -07004213 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4214 if (ret >= 0) {
4215 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4216 adev->bt_wb_speech_enabled = true;
4217 else
4218 adev->bt_wb_speech_enabled = false;
4219 }
4220
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004221 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4222 if (ret >= 0) {
4223 val = atoi(value);
4224 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004225 ALOGV("cache new ext disp type and edid");
4226 ret = platform_get_ext_disp_type(adev->platform);
4227 if (ret < 0) {
4228 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4229 return ret;
4230 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004231 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004232 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004233 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004234 /*
4235 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4236 * Per AudioPolicyManager, USB device is higher priority than WFD.
4237 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4238 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4239 * starting voice call on USB
4240 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004241 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4242 if (ret >= 0) {
4243 audio_extn_usb_add_device(val, atoi(value));
4244 }
vivek mehta344576a2016-04-12 18:56:03 -07004245 ALOGV("detected USB connect .. disable proxy");
4246 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004247 }
4248 }
4249
4250 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4251 if (ret >= 0) {
4252 val = atoi(value);
4253 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4254 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004255 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004256 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004257 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004258 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4259 if (ret >= 0) {
4260 audio_extn_usb_remove_device(val, atoi(value));
4261 }
vivek mehta344576a2016-04-12 18:56:03 -07004262 ALOGV("detected USB disconnect .. enable proxy");
4263 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004264 }
4265 }
4266
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304267 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4268 if (ret >= 0) {
4269 struct audio_usecase *usecase;
4270 struct listnode *node;
4271 list_for_each(node, &adev->usecase_list) {
4272 usecase = node_to_item(node, struct audio_usecase, list);
4273 if ((usecase->type == PCM_PLAYBACK) &&
4274 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4275 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304276 lock_output_stream(usecase->stream.out);
4277 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304278 //force device switch to re configure encoder
4279 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304280 audio_extn_a2dp_set_handoff_mode(false);
4281 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304282 break;
4283 }
4284 }
4285 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304286 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004287done:
4288 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004289 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304290error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004291 ALOGV("%s: exit with code(%d)", __func__, status);
4292 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293}
4294
4295static char* adev_get_parameters(const struct audio_hw_device *dev,
4296 const char *keys)
4297{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004298 struct audio_device *adev = (struct audio_device *)dev;
4299 struct str_parms *reply = str_parms_create();
4300 struct str_parms *query = str_parms_create_str(keys);
4301 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304302 char value[256] = {0};
4303 int ret = 0;
4304
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004305 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004306 if (reply) {
4307 str_parms_destroy(reply);
4308 }
4309 if (query) {
4310 str_parms_destroy(query);
4311 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004312 ALOGE("adev_get_parameters: failed to create query or reply");
4313 return NULL;
4314 }
4315
Naresh Tannirud7205b62014-06-20 02:54:48 +05304316 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4317 sizeof(value));
4318 if (ret >=0) {
4319 int val = 1;
4320 pthread_mutex_lock(&adev->snd_card_status.lock);
4321 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4322 val = 0;
4323 pthread_mutex_unlock(&adev->snd_card_status.lock);
4324 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4325 goto exit;
4326 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004327
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004328 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004329 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004330 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004331 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304332 pthread_mutex_unlock(&adev->lock);
4333
Naresh Tannirud7205b62014-06-20 02:54:48 +05304334exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004335 str = str_parms_to_str(reply);
4336 str_parms_destroy(query);
4337 str_parms_destroy(reply);
4338
4339 ALOGV("%s: exit: returns - %s", __func__, str);
4340 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341}
4342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004343static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344{
4345 return 0;
4346}
4347
4348static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4349{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004350 int ret;
4351 struct audio_device *adev = (struct audio_device *)dev;
4352 pthread_mutex_lock(&adev->lock);
4353 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004354 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004355 pthread_mutex_unlock(&adev->lock);
4356 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357}
4358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004359static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4360 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361{
4362 return -ENOSYS;
4363}
4364
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004365static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4366 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367{
4368 return -ENOSYS;
4369}
4370
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004371static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4372 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373{
4374 return -ENOSYS;
4375}
4376
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004377static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4378 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379{
4380 return -ENOSYS;
4381}
4382
4383static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4384{
4385 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 pthread_mutex_lock(&adev->lock);
4388 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004389 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004391 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004392 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004393 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004394 adev->current_call_output = NULL;
4395 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 }
4397 pthread_mutex_unlock(&adev->lock);
4398 return 0;
4399}
4400
4401static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4402{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004403 int ret;
4404
4405 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004406 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004407 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4408 pthread_mutex_unlock(&adev->lock);
4409
4410 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411}
4412
4413static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4414{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004415 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416 return 0;
4417}
4418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004419static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 const struct audio_config *config)
4421{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004422 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004424 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4425 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426}
4427
4428static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004429 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 audio_devices_t devices,
4431 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004432 struct audio_stream_in **stream_in,
4433 audio_input_flags_t flags __unused,
4434 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004435 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436{
4437 struct audio_device *adev = (struct audio_device *)dev;
4438 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004439 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004440 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004441 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304444 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4445 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448
4449 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004450
4451 if (!in) {
4452 ALOGE("failed to allocate input stream");
4453 return -ENOMEM;
4454 }
4455
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304456 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304457 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4458 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004459 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004460 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462 in->stream.common.get_sample_rate = in_get_sample_rate;
4463 in->stream.common.set_sample_rate = in_set_sample_rate;
4464 in->stream.common.get_buffer_size = in_get_buffer_size;
4465 in->stream.common.get_channels = in_get_channels;
4466 in->stream.common.get_format = in_get_format;
4467 in->stream.common.set_format = in_set_format;
4468 in->stream.common.standby = in_standby;
4469 in->stream.common.dump = in_dump;
4470 in->stream.common.set_parameters = in_set_parameters;
4471 in->stream.common.get_parameters = in_get_parameters;
4472 in->stream.common.add_audio_effect = in_add_audio_effect;
4473 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4474 in->stream.set_gain = in_set_gain;
4475 in->stream.read = in_read;
4476 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4477
4478 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004479 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481 in->standby = 1;
4482 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004483 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004484 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485
4486 /* Update config params with the requested sample rate and channels */
4487 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004488 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4489 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4490 is_low_latency = true;
4491#if LOW_LATENCY_CAPTURE_USE_CASE
4492 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4493#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004494 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004495 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004496
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004497 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004498 if (in->realtime) {
4499 in->config = pcm_config_audio_capture_rt;
4500 in->sample_rate = in->config.rate;
4501 in->af_period_multiplier = af_period_multiplier;
4502 } else {
4503 in->config = pcm_config_audio_capture;
4504 in->config.rate = config->sample_rate;
4505 in->sample_rate = config->sample_rate;
4506 in->af_period_multiplier = 1;
4507 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304508 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004510 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304511 if (adev->mode != AUDIO_MODE_IN_CALL) {
4512 ret = -EINVAL;
4513 goto err_open;
4514 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004515 if (config->sample_rate == 0)
4516 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4517 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4518 config->sample_rate != 8000) {
4519 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4520 ret = -EINVAL;
4521 goto err_open;
4522 }
4523 if (config->format == AUDIO_FORMAT_DEFAULT)
4524 config->format = AUDIO_FORMAT_PCM_16_BIT;
4525 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4526 config->format = AUDIO_FORMAT_PCM_16_BIT;
4527 ret = -EINVAL;
4528 goto err_open;
4529 }
4530
4531 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4532 in->config = pcm_config_afe_proxy_record;
4533 in->config.channels = channel_count;
4534 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304535 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304536 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4537 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004538 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004539 audio_extn_compr_cap_format_supported(config->format) &&
4540 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004541 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004542 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304543 /* restrict 24 bit capture for unprocessed source only
4544 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4545 */
4546 if (config->format == AUDIO_FORMAT_DEFAULT) {
4547 config->format = AUDIO_FORMAT_PCM_16_BIT;
4548 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4549 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4550 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4551 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4552 bool ret_error = false;
4553 in->bit_width = 24;
4554 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4555 from HAL is 24_packed and 8_24
4556 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4557 24_packed return error indicating supported format is 24_packed
4558 *> In case of any other source requesting 24 bit or float return error
4559 indicating format supported is 16 bit only.
4560
4561 on error flinger will retry with supported format passed
4562 */
4563 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4564 (source != AUDIO_SOURCE_CAMCORDER)) {
4565 config->format = AUDIO_FORMAT_PCM_16_BIT;
4566 if( config->sample_rate > 48000)
4567 config->sample_rate = 48000;
4568 ret_error = true;
4569 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4570 in->config.format = PCM_FORMAT_S24_3LE;
4571 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4572 in->config.format = PCM_FORMAT_S24_LE;
4573 } else {
4574 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4575 ret_error = true;
4576 }
4577
4578 if (ret_error) {
4579 ret = -EINVAL;
4580 goto err_open;
4581 }
4582 }
4583
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004584 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004585 if (!in->realtime) {
4586 in->format = config->format;
4587 frame_size = audio_stream_in_frame_size(&in->stream);
4588 buffer_size = get_input_buffer_size(config->sample_rate,
4589 config->format,
4590 channel_count,
4591 is_low_latency);
4592 in->config.period_size = buffer_size / frame_size;
4593 }
4594
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004595 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4596 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4597 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004598 (in->config.rate == 8000 || in->config.rate == 16000 ||
4599 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004600 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4601 voice_extn_compress_voip_open_input_stream(in);
4602 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004605 /* This stream could be for sound trigger lab,
4606 get sound trigger pcm if present */
4607 audio_extn_sound_trigger_check_and_get_session(in);
4608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004610 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612
4613err_open:
4614 free(in);
4615 *stream_in = NULL;
4616 return ret;
4617}
4618
4619static void adev_close_input_stream(struct audio_hw_device *dev,
4620 struct audio_stream_in *stream)
4621{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004622 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004623 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004624 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304625
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304626 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004627
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304628 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004629 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304630
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004631 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304632 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004633 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304634 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004635 if (ret != 0)
4636 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4637 __func__, ret);
4638 } else
4639 in_standby(&stream->common);
4640
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004641 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004642 audio_extn_ssr_deinit();
4643 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644
Mingming Yine62d7842013-10-25 16:26:03 -07004645 if(audio_extn_compr_cap_enabled() &&
4646 audio_extn_compr_cap_format_supported(in->config.format))
4647 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004648
Mingming Yinfd7607b2016-01-22 12:48:44 -08004649 if (in->is_st_session) {
4650 ALOGV("%s: sound trigger pcm stop lab", __func__);
4651 audio_extn_sound_trigger_stop_lab(in);
4652 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004653 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 return;
4655}
4656
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004657static int adev_dump(const audio_hw_device_t *device __unused,
4658 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659{
4660 return 0;
4661}
4662
4663static int adev_close(hw_device_t *device)
4664{
4665 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004666
4667 if (!adev)
4668 return 0;
4669
4670 pthread_mutex_lock(&adev_init_lock);
4671
4672 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004673 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004674 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304675 if (audio_extn_qaf_is_enabled())
4676 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004677 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004678 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004679 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004680 free(adev->snd_dev_ref_cnt);
4681 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004682 if (adev->adm_deinit)
4683 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004684 free(device);
4685 adev = NULL;
4686 }
4687 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 return 0;
4690}
4691
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004692/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4693 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4694 * just that it _might_ work.
4695 */
4696static int period_size_is_plausible_for_low_latency(int period_size)
4697{
4698 switch (period_size) {
4699 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004700 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004701 case 240:
4702 case 320:
4703 case 480:
4704 return 1;
4705 default:
4706 return 0;
4707 }
4708}
4709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710static int adev_open(const hw_module_t *module, const char *name,
4711 hw_device_t **device)
4712{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304713 int ret;
4714
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004715 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4717
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004718 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004719 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004720 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004721 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004722 ALOGD("%s: returning existing instance of adev", __func__);
4723 ALOGD("%s: exit", __func__);
4724 pthread_mutex_unlock(&adev_init_lock);
4725 return 0;
4726 }
4727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728 adev = calloc(1, sizeof(struct audio_device));
4729
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004730 if (!adev) {
4731 pthread_mutex_unlock(&adev_init_lock);
4732 return -ENOMEM;
4733 }
4734
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004735 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4738 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4739 adev->device.common.module = (struct hw_module_t *)module;
4740 adev->device.common.close = adev_close;
4741
4742 adev->device.init_check = adev_init_check;
4743 adev->device.set_voice_volume = adev_set_voice_volume;
4744 adev->device.set_master_volume = adev_set_master_volume;
4745 adev->device.get_master_volume = adev_get_master_volume;
4746 adev->device.set_master_mute = adev_set_master_mute;
4747 adev->device.get_master_mute = adev_get_master_mute;
4748 adev->device.set_mode = adev_set_mode;
4749 adev->device.set_mic_mute = adev_set_mic_mute;
4750 adev->device.get_mic_mute = adev_get_mic_mute;
4751 adev->device.set_parameters = adev_set_parameters;
4752 adev->device.get_parameters = adev_get_parameters;
4753 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4754 adev->device.open_output_stream = adev_open_output_stream;
4755 adev->device.close_output_stream = adev_close_output_stream;
4756 adev->device.open_input_stream = adev_open_input_stream;
4757 adev->device.close_input_stream = adev_close_input_stream;
4758 adev->device.dump = adev_dump;
4759
4760 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004762 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004763 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004766 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004767 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004768 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004769 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004770 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004771 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004772 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004773 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304774 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304775 adev->perf_lock_opts[0] = 0x101;
4776 adev->perf_lock_opts[1] = 0x20E;
4777 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304778
4779 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4780 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004782 adev->platform = platform_init(adev);
4783 if (!adev->platform) {
4784 free(adev->snd_dev_ref_cnt);
4785 free(adev);
4786 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4787 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004788 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304789 pthread_mutex_destroy(&adev->lock);
4790 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004791 return -EINVAL;
4792 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004793
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304794 if (audio_extn_qaf_is_enabled()) {
4795 ret = audio_extn_qaf_init(adev);
4796 if (ret < 0) {
4797 free(adev);
4798 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4799 *device = NULL;
4800 pthread_mutex_unlock(&adev_init_lock);
4801 pthread_mutex_destroy(&adev->lock);
4802 return ret;
4803 }
4804
4805 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4806 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4807 }
4808
Naresh Tanniru4c630392014-05-12 01:05:52 +05304809 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4810
Eric Laurentc4aef752013-09-12 17:45:53 -07004811 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4812 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4813 if (adev->visualizer_lib == NULL) {
4814 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4815 } else {
4816 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4817 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004818 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004819 "visualizer_hal_start_output");
4820 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004821 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004822 "visualizer_hal_stop_output");
4823 }
4824 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004825 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004826 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004827 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004828
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004829 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4830 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4831 if (adev->offload_effects_lib == NULL) {
4832 ALOGE("%s: DLOPEN failed for %s", __func__,
4833 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4834 } else {
4835 ALOGV("%s: DLOPEN successful for %s", __func__,
4836 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4837 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304838 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004839 "offload_effects_bundle_hal_start_output");
4840 adev->offload_effects_stop_output =
4841 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4842 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004843 adev->offload_effects_set_hpx_state =
4844 (int (*)(bool))dlsym(adev->offload_effects_lib,
4845 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304846 adev->offload_effects_get_parameters =
4847 (void (*)(struct str_parms *, struct str_parms *))
4848 dlsym(adev->offload_effects_lib,
4849 "offload_effects_bundle_get_parameters");
4850 adev->offload_effects_set_parameters =
4851 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4852 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004853 }
4854 }
4855
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004856 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4857 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4858 if (adev->adm_lib == NULL) {
4859 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4860 } else {
4861 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4862 adev->adm_init = (adm_init_t)
4863 dlsym(adev->adm_lib, "adm_init");
4864 adev->adm_deinit = (adm_deinit_t)
4865 dlsym(adev->adm_lib, "adm_deinit");
4866 adev->adm_register_input_stream = (adm_register_input_stream_t)
4867 dlsym(adev->adm_lib, "adm_register_input_stream");
4868 adev->adm_register_output_stream = (adm_register_output_stream_t)
4869 dlsym(adev->adm_lib, "adm_register_output_stream");
4870 adev->adm_deregister_stream = (adm_deregister_stream_t)
4871 dlsym(adev->adm_lib, "adm_deregister_stream");
4872 adev->adm_request_focus = (adm_request_focus_t)
4873 dlsym(adev->adm_lib, "adm_request_focus");
4874 adev->adm_abandon_focus = (adm_abandon_focus_t)
4875 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004876 adev->adm_set_config = (adm_set_config_t)
4877 dlsym(adev->adm_lib, "adm_set_config");
4878 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4879 dlsym(adev->adm_lib, "adm_request_focus_v2");
4880 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4881 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4882 adev->adm_on_routing_change = (adm_on_routing_change_t)
4883 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004884 }
4885 }
4886
Mingming Yin514a8bc2014-07-29 15:22:21 -07004887 adev->bt_wb_speech_enabled = false;
4888
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004889 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890 *device = &adev->device.common;
4891
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004892 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4893 &adev->streams_output_cfg_list);
4894
Kiran Kandi910e1862013-10-29 13:29:42 -07004895 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004896
4897 char value[PROPERTY_VALUE_MAX];
4898 int trial;
4899 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4900 trial = atoi(value);
4901 if (period_size_is_plausible_for_low_latency(trial)) {
4902 pcm_config_low_latency.period_size = trial;
4903 pcm_config_low_latency.start_threshold = trial / 4;
4904 pcm_config_low_latency.avail_min = trial / 4;
4905 configured_low_latency_capture_period_size = trial;
4906 }
4907 }
4908 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4909 trial = atoi(value);
4910 if (period_size_is_plausible_for_low_latency(trial)) {
4911 configured_low_latency_capture_period_size = trial;
4912 }
4913 }
4914
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004915 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4916 af_period_multiplier = atoi(value);
4917 if (af_period_multiplier < 0)
4918 af_period_multiplier = 2;
4919 else if (af_period_multiplier > 4)
4920 af_period_multiplier = 4;
4921
4922 ALOGV("new period_multiplier = %d", af_period_multiplier);
4923 }
4924
vivek mehta446c3962015-09-14 10:57:35 -07004925 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004926 pthread_mutex_unlock(&adev_init_lock);
4927
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004928 if (adev->adm_init)
4929 adev->adm_data = adev->adm_init();
4930
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304931 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004932 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933 return 0;
4934}
4935
4936static struct hw_module_methods_t hal_module_methods = {
4937 .open = adev_open,
4938};
4939
4940struct audio_module HAL_MODULE_INFO_SYM = {
4941 .common = {
4942 .tag = HARDWARE_MODULE_TAG,
4943 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4944 .hal_api_version = HARDWARE_HAL_API_VERSION,
4945 .id = AUDIO_HARDWARE_MODULE_ID,
4946 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004947 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948 .methods = &hal_module_methods,
4949 },
4950};