blob: b86040cb028d01fc4a2e6256031dfe550bd1dec2 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530625static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530626{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530627 ALOGV("%s", __func__);
628 audio_route_apply_and_update_path(adev->audio_route,
629 "asrc-mode");
630 adev->asrc_mode_enabled = true;
631}
632
633static void disable_asrc_mode(struct audio_device *adev)
634{
635 ALOGV("%s", __func__);
636 audio_route_reset_and_update_path(adev->audio_route,
637 "asrc-mode");
638 adev->asrc_mode_enabled = false;
639}
640
641/*
642 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
643 * 44.1 or Native DSD backends are enabled for any of current use case.
644 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
645 * - Disable current mix path use case(Headphone backend) and re-enable it with
646 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
647 * e.g. Naitve DSD or Headphone 44.1 -> + 48
648 */
649static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
650{
651 ALOGV("%s snd device %d", __func__, snd_device);
652 int new_backend_idx = platform_get_backend_index(snd_device);
653
654 if (((new_backend_idx == HEADPHONE_BACKEND) ||
655 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
656 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
657 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530658 struct listnode *node = NULL;
659 struct audio_usecase *uc = NULL;
660 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530662
663 list_for_each(node, &adev->usecase_list) {
664 uc = node_to_item(node, struct audio_usecase, list);
665 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530666 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530667 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
668
669 if((new_backend_idx == HEADPHONE_BACKEND) &&
670 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
671 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530672 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
673 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530674 enable_asrc_mode(adev);
675 break;
676 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
677 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
678 (usecase_backend_idx == HEADPHONE_BACKEND)) {
679 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
680 __func__);
681 disable_audio_route(adev, uc);
682 disable_snd_device(adev, uc->out_snd_device);
683 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
684 if (new_backend_idx == DSD_NATIVE_BACKEND)
685 audio_route_apply_and_update_path(adev->audio_route,
686 "hph-true-highquality-mode");
687 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
688 (curr_out->bit_width >= 24))
689 audio_route_apply_and_update_path(adev->audio_route,
690 "hph-highquality-mode");
691 enable_asrc_mode(adev);
692 enable_snd_device(adev, uc->out_snd_device);
693 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530694 break;
695 }
696 }
697 }
698 }
699}
700
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700701int pcm_ioctl(struct pcm *pcm, int request, ...)
702{
703 va_list ap;
704 void * arg;
705 int pcm_fd = *(int*)pcm;
706
707 va_start(ap, request);
708 arg = va_arg(ap, void *);
709 va_end(ap);
710
711 return ioctl(pcm_fd, request, arg);
712}
713
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700714int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700715 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800716{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700718 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800719
720 if (usecase == NULL)
721 return -EINVAL;
722
723 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
724
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800725 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800727 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800729
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800730#ifdef DS1_DOLBY_DAP_ENABLED
731 audio_extn_dolby_set_dmid(adev);
732 audio_extn_dolby_set_endpoint(adev);
733#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700734 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700735 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530736 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700737 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530738 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800739 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700740 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700741 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700742 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743 ALOGV("%s: exit", __func__);
744 return 0;
745}
746
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700747int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700748 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700751 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800752
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530753 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800754 return -EINVAL;
755
756 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700757 if (usecase->type == PCM_CAPTURE)
758 snd_device = usecase->in_snd_device;
759 else
760 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800761 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700762 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700763 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700764 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700765 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530766 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767 ALOGV("%s: exit", __func__);
768 return 0;
769}
770
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700771int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700772 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530774 int i, num_devices = 0;
775 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700776 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
777
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800778 if (snd_device < SND_DEVICE_MIN ||
779 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800780 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800781 return -EINVAL;
782 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783
784 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700785
786 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
787 ALOGE("%s: Invalid sound device returned", __func__);
788 return -EINVAL;
789 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700791 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700792 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 return 0;
794 }
795
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700797 if (audio_extn_spkr_prot_is_enabled())
798 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700799
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800800 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
801 audio_extn_spkr_prot_is_enabled()) {
802 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700803 adev->snd_dev_ref_cnt[snd_device]--;
804 return -EINVAL;
805 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200806 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800807 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800808 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200809 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800810 return -EINVAL;
811 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530812 } else if (platform_can_split_snd_device(adev->platform, snd_device,
813 &num_devices, new_snd_devices)) {
814 for (i = 0; i < num_devices; i++) {
815 enable_snd_device(adev, new_snd_devices[i]);
816 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800817 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700818 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530819
820 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
821 (audio_extn_a2dp_start_playback() < 0)) {
822 ALOGE(" fail to configure A2dp control path ");
823 return -EINVAL;
824 }
825
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700826 /* due to the possibility of calibration overwrite between listen
827 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700828 audio_extn_sound_trigger_update_device_status(snd_device,
829 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530830 audio_extn_listen_update_device_status(snd_device,
831 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700832 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700833 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700834 audio_extn_sound_trigger_update_device_status(snd_device,
835 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530836 audio_extn_listen_update_device_status(snd_device,
837 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700838 return -EINVAL;
839 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300840 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700841 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530842
843 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
844 !adev->native_playback_enabled &&
845 audio_is_true_native_stream_active(adev)) {
846 ALOGD("%s: %d: napb: enabling native mode in hardware",
847 __func__, __LINE__);
848 audio_route_apply_and_update_path(adev->audio_route,
849 "true-native-mode");
850 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853 return 0;
854}
855
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700856int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700857 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530859 int i, num_devices = 0;
860 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700861 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
862
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800863 if (snd_device < SND_DEVICE_MIN ||
864 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800865 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800866 return -EINVAL;
867 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
869 ALOGE("%s: device ref cnt is already 0", __func__);
870 return -EINVAL;
871 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700874
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
876 ALOGE("%s: Invalid sound device returned", __func__);
877 return -EINVAL;
878 }
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700881 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530882
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800883 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
884 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700885 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530886 } else if (platform_can_split_snd_device(adev->platform, snd_device,
887 &num_devices, new_snd_devices)) {
888 for (i = 0; i < num_devices; i++) {
889 disable_snd_device(adev, new_snd_devices[i]);
890 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300891 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700892 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300893 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700894
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530895 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
896 audio_extn_a2dp_stop_playback();
897
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700898 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530899 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530900 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
901 adev->native_playback_enabled) {
902 ALOGD("%s: %d: napb: disabling native mode in hardware",
903 __func__, __LINE__);
904 audio_route_reset_and_update_path(adev->audio_route,
905 "true-native-mode");
906 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530907 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
908 adev->asrc_mode_enabled) {
909 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910 disable_asrc_mode(adev);
911 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530912 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530913
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200914 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700915 audio_extn_sound_trigger_update_device_status(snd_device,
916 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530917 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800918 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922}
923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530925 struct audio_usecase *uc_info,
926 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927{
928 struct listnode *node;
929 struct audio_usecase *usecase;
930 bool switch_device[AUDIO_USECASE_MAX];
931 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530932 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 /*
934 * This function is to make sure that all the usecases that are active on
935 * the hardware codec backend are always routed to any one device that is
936 * handled by the hardware codec.
937 * For example, if low-latency and deep-buffer usecases are currently active
938 * on speaker and out_set_parameters(headset) is received on low-latency
939 * output, then we have to make sure deep-buffer is also switched to headset,
940 * because of the limitation that both the devices cannot be enabled
941 * at the same time as they share the same backend.
942 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700943 /*
944 * This call is to check if we need to force routing for a particular stream
945 * If there is a backend configuration change for the device when a
946 * new stream starts, then ADM needs to be closed and re-opened with the new
947 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800948 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700949 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800950 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
951 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530952 /* For a2dp device reconfigure all active sessions
953 * with new AFE encoder format based on a2dp state
954 */
955 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
956 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
957 audio_extn_a2dp_is_force_device_switch()) {
958 force_routing = true;
959 force_restart_session = true;
960 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 ALOGD("%s:becf: force routing %d", __func__, force_routing);
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800964 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800965 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 for (i = 0; i < AUDIO_USECASE_MAX; i++)
967 switch_device[i] = false;
968
969 list_for_each(node, &adev->usecase_list) {
970 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800971
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530972 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
973 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530974 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530975 platform_get_snd_device_name(usecase->out_snd_device),
976 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800977 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530978 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530979 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530980 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
981 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530982 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530983 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530984 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
985
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530986 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
987 __func__, use_case_table[usecase->id],
988 platform_get_snd_device_name(usecase->out_snd_device));
989 disable_audio_route(adev, usecase);
990 switch_device[usecase->id] = true;
991 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700992 }
993 }
994
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530995 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
996 num_uc_to_switch);
997
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700999 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301001 /* Make sure the previous devices to be disabled first and then enable the
1002 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001006 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001007 }
1008 }
1009
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001010 list_for_each(node, &adev->usecase_list) {
1011 usecase = node_to_item(node, struct audio_usecase, list);
1012 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001013 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001014 }
1015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 /* Re-route all the usecases on the shared backend other than the
1018 specified usecase to new snd devices */
1019 list_for_each(node, &adev->usecase_list) {
1020 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301021 /* Update the out_snd_device only before enabling the audio route */
1022 if (switch_device[usecase->id]) {
1023 usecase->out_snd_device = snd_device;
1024 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301025 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301026 use_case_table[usecase->id],
1027 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301028 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301029 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 }
1031 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 }
1033}
1034
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301035static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 struct audio_usecase *uc_info,
1037 snd_device_t snd_device)
1038{
1039 struct listnode *node;
1040 struct audio_usecase *usecase;
1041 bool switch_device[AUDIO_USECASE_MAX];
1042 int i, num_uc_to_switch = 0;
1043
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301044 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1045 snd_device);
1046 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001047 /*
1048 * This function is to make sure that all the active capture usecases
1049 * are always routed to the same input sound device.
1050 * For example, if audio-record and voice-call usecases are currently
1051 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1052 * is received for voice call then we have to make sure that audio-record
1053 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1054 * because of the limitation that two devices cannot be enabled
1055 * at the same time if they share the same backend.
1056 */
1057 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1058 switch_device[i] = false;
1059
1060 list_for_each(node, &adev->usecase_list) {
1061 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001062 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001063 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301064 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001065 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301066 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001067 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001068 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001069 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1070 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001071 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001072 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001073 switch_device[usecase->id] = true;
1074 num_uc_to_switch++;
1075 }
1076 }
1077
1078 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001079 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001080
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301081 /* Make sure the previous devices to be disabled first and then enable the
1082 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
1085 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001087 }
1088 }
1089
1090 list_for_each(node, &adev->usecase_list) {
1091 usecase = node_to_item(node, struct audio_usecase, list);
1092 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001093 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001094 }
1095 }
1096
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001097 /* Re-route all the usecases on the shared backend other than the
1098 specified usecase to new snd devices */
1099 list_for_each(node, &adev->usecase_list) {
1100 usecase = node_to_item(node, struct audio_usecase, list);
1101 /* Update the in_snd_device only before enabling the audio route */
1102 if (switch_device[usecase->id] ) {
1103 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001104 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301105 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001106 }
1107 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001108 }
1109}
1110
Mingming Yin3a941d42016-02-17 18:08:05 -08001111static void reset_hdmi_sink_caps(struct stream_out *out) {
1112 int i = 0;
1113
1114 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1115 out->supported_channel_masks[i] = 0;
1116 }
1117 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1118 out->supported_formats[i] = 0;
1119 }
1120 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1121 out->supported_sample_rates[i] = 0;
1122 }
1123}
1124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001126static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127{
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001129 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130
Mingming Yin3a941d42016-02-17 18:08:05 -08001131 reset_hdmi_sink_caps(out);
1132
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001133 /* Cache ext disp type */
1134 ret = platform_get_ext_disp_type(adev->platform);
1135 if (ret < 0) {
1136 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
1137 return ret;
1138 }
1139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001142 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001143 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001144 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1145 case 6:
1146 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1147 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1148 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1149 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1150 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1151 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152 break;
1153 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001154 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001155 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156 break;
1157 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001158
1159 // check channel format caps
1160 i = 0;
1161 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1162 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1163 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1164 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1165 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1166 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1167 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1168 }
1169
1170 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1171 ALOGV(":%s HDMI supports DTS format", __func__);
1172 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1173 }
1174
1175 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1176 ALOGV(":%s HDMI supports DTS HD format", __func__);
1177 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1178 }
1179
1180
1181 // check sample rate caps
1182 i = 0;
1183 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1184 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1185 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1186 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1187 }
1188 }
1189
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001190 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191}
1192
Alexy Josephb1379942016-01-29 15:49:38 -08001193audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001194 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001195{
1196 struct audio_usecase *usecase;
1197 struct listnode *node;
1198
1199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001201 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001202 ALOGV("%s: usecase id %d", __func__, usecase->id);
1203 return usecase->id;
1204 }
1205 }
1206 return USECASE_INVALID;
1207}
1208
Alexy Josephb1379942016-01-29 15:49:38 -08001209struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001210 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211{
1212 struct audio_usecase *usecase;
1213 struct listnode *node;
1214
1215 list_for_each(node, &adev->usecase_list) {
1216 usecase = node_to_item(node, struct audio_usecase, list);
1217 if (usecase->id == uc_id)
1218 return usecase;
1219 }
1220 return NULL;
1221}
1222
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301223/*
1224 * is a true native playback active
1225 */
1226bool audio_is_true_native_stream_active(struct audio_device *adev)
1227{
1228 bool active = false;
1229 int i = 0;
1230 struct listnode *node;
1231
1232 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1233 ALOGV("%s:napb: not in true mode or non hdphones device",
1234 __func__);
1235 active = false;
1236 goto exit;
1237 }
1238
1239 list_for_each(node, &adev->usecase_list) {
1240 struct audio_usecase *uc;
1241 uc = node_to_item(node, struct audio_usecase, list);
1242 struct stream_out *curr_out =
1243 (struct stream_out*) uc->stream.out;
1244
1245 if (curr_out && PCM_PLAYBACK == uc->type) {
1246 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1247 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1248 uc->id, curr_out->sample_rate,
1249 curr_out->bit_width,
1250 platform_get_snd_device_name(uc->out_snd_device));
1251
1252 if (is_offload_usecase(uc->id) &&
1253 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1254 active = true;
1255 ALOGD("%s:napb:native stream detected", __func__);
1256 }
1257 }
1258 }
1259exit:
1260 return active;
1261}
1262
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301263/*
1264 * if native DSD playback active
1265 */
1266bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1267{
1268 bool active = false;
1269 struct listnode *node = NULL;
1270 struct audio_usecase *uc = NULL;
1271 struct stream_out *curr_out = NULL;
1272
1273 list_for_each(node, &adev->usecase_list) {
1274 uc = node_to_item(node, struct audio_usecase, list);
1275 curr_out = (struct stream_out*) uc->stream.out;
1276
1277 if (curr_out && PCM_PLAYBACK == uc->type &&
1278 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1279 active = true;
1280 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301281 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301282 }
1283 }
1284 return active;
1285}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301286
1287static bool force_device_switch(struct audio_usecase *usecase)
1288{
1289 bool ret = false;
1290 bool is_it_true_mode = false;
1291
1292 if (is_offload_usecase(usecase->id) &&
1293 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001294 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1295 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1296 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301297 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1298 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1299 (!is_it_true_mode && adev->native_playback_enabled)){
1300 ret = true;
1301 ALOGD("napb: time to toggle native mode");
1302 }
1303 }
1304
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301305 // Force all a2dp output devices to reconfigure for proper AFE encode format
1306 if((usecase->stream.out) &&
1307 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1308 audio_extn_a2dp_is_force_device_switch()) {
1309 ALOGD("Force a2dp device switch to update new encoder config");
1310 ret = true;
1311 }
1312
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301313 return ret;
1314}
1315
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001316int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001318 snd_device_t out_snd_device = SND_DEVICE_NONE;
1319 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320 struct audio_usecase *usecase = NULL;
1321 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001322 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001323 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001324 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301327 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1328
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 usecase = get_usecase_from_list(adev, uc_id);
1330 if (usecase == NULL) {
1331 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1332 return -EINVAL;
1333 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001335 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001336 (usecase->type == VOIP_CALL) ||
1337 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001338 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001339 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001340 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001341 usecase->devices = usecase->stream.out->devices;
1342 } else {
1343 /*
1344 * If the voice call is active, use the sound devices of voice call usecase
1345 * so that it would not result any device switch. All the usecases will
1346 * be switched to new device when select_devices() is called for voice call
1347 * usecase. This is to avoid switching devices for voice call when
1348 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001349 * choose voice call device only if the use case device is
1350 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001351 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001352 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001353 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001354 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001355 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1356 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301357 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1358 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001359 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001360 in_snd_device = vc_usecase->in_snd_device;
1361 out_snd_device = vc_usecase->out_snd_device;
1362 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001363 } else if (voice_extn_compress_voip_is_active(adev)) {
1364 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001365 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001366 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1367 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001368 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001369 in_snd_device = voip_usecase->in_snd_device;
1370 out_snd_device = voip_usecase->out_snd_device;
1371 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001372 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001373 hfp_ucid = audio_extn_hfp_get_usecase();
1374 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001375 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001376 in_snd_device = hfp_usecase->in_snd_device;
1377 out_snd_device = hfp_usecase->out_snd_device;
1378 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 }
1380 if (usecase->type == PCM_PLAYBACK) {
1381 usecase->devices = usecase->stream.out->devices;
1382 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001383 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001384 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001385 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001386 if (usecase->stream.out == adev->primary_output &&
1387 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001388 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001389 select_devices(adev, adev->active_input->usecase);
1390 }
1391 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 } else if (usecase->type == PCM_CAPTURE) {
1393 usecase->devices = usecase->stream.in->device;
1394 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001395 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001396 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001397 if (adev->active_input &&
1398 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301399 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1400 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1401 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001402 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001403 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001404 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1405 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001406 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001407 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001408 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001409 }
1410 }
1411
1412 if (out_snd_device == usecase->out_snd_device &&
1413 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301414
1415 if (!force_device_switch(usecase))
1416 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417 }
1418
sangwoobc677242013-08-08 16:53:43 +09001419 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001420 out_snd_device, platform_get_snd_device_name(out_snd_device),
1421 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 /*
1424 * Limitation: While in call, to do a device switch we need to disable
1425 * and enable both RX and TX devices though one of them is same as current
1426 * device.
1427 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001428 if ((usecase->type == VOICE_CALL) &&
1429 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1430 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001431 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001432 }
1433
1434 if (((usecase->type == VOICE_CALL) ||
1435 (usecase->type == VOIP_CALL)) &&
1436 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1437 /* Disable sidetone only if voice/voip call already exists */
1438 if (voice_is_call_state_active(adev) ||
1439 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001440 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001441 }
1442
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 /* Disable current sound devices */
1444 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001445 disable_audio_route(adev, usecase);
1446 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 }
1448
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001450 disable_audio_route(adev, usecase);
1451 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 }
1453
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001454 /* Applicable only on the targets that has external modem.
1455 * New device information should be sent to modem before enabling
1456 * the devices to reduce in-call device switch time.
1457 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001458 if ((usecase->type == VOICE_CALL) &&
1459 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1460 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001461 status = platform_switch_voice_call_enable_device_config(adev->platform,
1462 out_snd_device,
1463 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001464 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001465
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 /* Enable new sound devices */
1467 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001468 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301469 if (platform_check_codec_asrc_support(adev->platform))
1470 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001471 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472 }
1473
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001474 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301475 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001476 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001477 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478
Avinash Vaish71a8b972014-07-24 15:36:33 +05301479 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001480 status = platform_switch_voice_call_device_post(adev->platform,
1481 out_snd_device,
1482 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301483 enable_audio_route_for_voice_usecases(adev, usecase);
1484 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001485
sangwoo170731f2013-06-08 15:36:36 +09001486 usecase->in_snd_device = in_snd_device;
1487 usecase->out_snd_device = out_snd_device;
1488
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301489 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001490 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301491 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001492 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301493 usecase->stream.out->flags,
1494 usecase->stream.out->format,
1495 usecase->stream.out->sample_rate,
1496 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301497 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301498 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001499 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001500
1501 /* Notify device change info to effect clients registered */
1502 audio_extn_gef_notify_device_config(
1503 usecase->stream.out->devices,
1504 usecase->stream.out->channel_mask,
1505 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301506 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001507
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001508 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001509
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001510 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1511 /* Enable sidetone only if other voice/voip call already exists */
1512 if (voice_is_call_state_active(adev) ||
1513 voice_extn_compress_voip_is_started(adev))
1514 voice_set_sidetone(adev, out_snd_device, true);
1515 }
1516
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001517 /* Applicable only on the targets that has external modem.
1518 * Enable device command should be sent to modem only after
1519 * enabling voice call mixer controls
1520 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001521 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001522 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1523 out_snd_device,
1524 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301525 ALOGD("%s: done",__func__);
1526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527 return status;
1528}
1529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530static int stop_input_stream(struct stream_in *in)
1531{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301532 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 struct audio_usecase *uc_info;
1534 struct audio_device *adev = in->dev;
1535
Eric Laurentc8400632013-02-14 19:04:54 -08001536 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537
Eric Laurent994a6932013-07-17 11:51:42 -07001538 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001539 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 uc_info = get_usecase_from_list(adev, in->usecase);
1541 if (uc_info == NULL) {
1542 ALOGE("%s: Could not find the usecase (%d) in the list",
1543 __func__, in->usecase);
1544 return -EINVAL;
1545 }
1546
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001547 /* Close in-call recording streams */
1548 voice_check_and_stop_incall_rec_usecase(adev, in);
1549
Eric Laurent150dbfe2013-02-27 14:31:02 -08001550 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001551 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552
1553 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001554 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001556 list_remove(&uc_info->list);
1557 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558
Eric Laurent994a6932013-07-17 11:51:42 -07001559 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560 return ret;
1561}
1562
1563int start_input_stream(struct stream_in *in)
1564{
1565 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001566 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 struct audio_usecase *uc_info;
1568 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301569 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570
Mingming Yin2664a5b2015-09-03 10:53:11 -07001571 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1572 if (get_usecase_from_list(adev, usecase) == NULL)
1573 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301574 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1575 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001576
Naresh Tanniru80659832014-06-04 18:17:56 +05301577
1578 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301579 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301580 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301581 goto error_config;
1582 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301583
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001584 /* Check if source matches incall recording usecase criteria */
1585 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1586 if (ret)
1587 goto error_config;
1588 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001589 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1590
1591 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1592 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1593 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001594 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001595 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001596
Eric Laurentb23d5282013-05-14 15:27:20 -07001597 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 if (in->pcm_device_id < 0) {
1599 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1600 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001601 ret = -EINVAL;
1602 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604
1605 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001607
1608 if (!uc_info) {
1609 ret = -ENOMEM;
1610 goto error_config;
1611 }
1612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613 uc_info->id = in->usecase;
1614 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001615 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001616 uc_info->devices = in->device;
1617 uc_info->in_snd_device = SND_DEVICE_NONE;
1618 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001620 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301621 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1622 adev->perf_lock_opts,
1623 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301626 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1627 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001628
1629 unsigned int flags = PCM_IN;
1630 unsigned int pcm_open_retry_count = 0;
1631
1632 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1633 flags |= PCM_MMAP | PCM_NOIRQ;
1634 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001635 } else if (in->realtime) {
1636 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001637 }
1638
1639 while (1) {
1640 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1641 flags, &in->config);
1642 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1643 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1644 if (in->pcm != NULL) {
1645 pcm_close(in->pcm);
1646 in->pcm = NULL;
1647 }
1648 if (pcm_open_retry_count-- == 0) {
1649 ret = -EIO;
1650 goto error_open;
1651 }
1652 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1653 continue;
1654 }
1655 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001657
1658 ALOGV("%s: pcm_prepare", __func__);
1659 ret = pcm_prepare(in->pcm);
1660 if (ret < 0) {
1661 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1662 pcm_close(in->pcm);
1663 in->pcm = NULL;
1664 goto error_open;
1665 }
1666
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001667 register_in_stream(in);
1668 if (in->realtime) {
1669 ret = pcm_start(in->pcm);
1670 if (ret < 0)
1671 goto error_open;
1672 }
1673
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301674 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001675 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001676
Eric Laurentc8400632013-02-14 19:04:54 -08001677 return ret;
1678
1679error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301680 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001682error_config:
1683 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301684 /*
1685 * sleep 50ms to allow sufficient time for kernel
1686 * drivers to recover incases like SSR.
1687 */
1688 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001689 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001690
1691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692}
1693
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001694void lock_input_stream(struct stream_in *in)
1695{
1696 pthread_mutex_lock(&in->pre_lock);
1697 pthread_mutex_lock(&in->lock);
1698 pthread_mutex_unlock(&in->pre_lock);
1699}
1700
1701void lock_output_stream(struct stream_out *out)
1702{
1703 pthread_mutex_lock(&out->pre_lock);
1704 pthread_mutex_lock(&out->lock);
1705 pthread_mutex_unlock(&out->pre_lock);
1706}
1707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708/* must be called with out->lock locked */
1709static int send_offload_cmd_l(struct stream_out* out, int command)
1710{
1711 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1712
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001713 if (!cmd) {
1714 ALOGE("failed to allocate mem for command 0x%x", command);
1715 return -ENOMEM;
1716 }
1717
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 ALOGVV("%s %d", __func__, command);
1719
1720 cmd->cmd = command;
1721 list_add_tail(&out->offload_cmd_list, &cmd->node);
1722 pthread_cond_signal(&out->offload_cond);
1723 return 0;
1724}
1725
1726/* must be called iwth out->lock locked */
1727static void stop_compressed_output_l(struct stream_out *out)
1728{
1729 out->offload_state = OFFLOAD_STATE_IDLE;
1730 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001731 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 if (out->compr != NULL) {
1733 compress_stop(out->compr);
1734 while (out->offload_thread_blocked) {
1735 pthread_cond_wait(&out->cond, &out->lock);
1736 }
1737 }
1738}
1739
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001740bool is_offload_usecase(audio_usecase_t uc_id)
1741{
1742 unsigned int i;
1743 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1744 if (uc_id == offload_usecases[i])
1745 return true;
1746 }
1747 return false;
1748}
1749
vivek mehta446c3962015-09-14 10:57:35 -07001750static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001751{
vivek mehta446c3962015-09-14 10:57:35 -07001752 audio_usecase_t ret_uc = USECASE_INVALID;
1753 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001754 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001755 if (!adev->multi_offload_enable) {
1756 if (is_direct_pcm)
1757 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1758 else
1759 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001760
vivek mehta446c3962015-09-14 10:57:35 -07001761 pthread_mutex_lock(&adev->lock);
1762 if (get_usecase_from_list(adev, ret_uc) != NULL)
1763 ret_uc = USECASE_INVALID;
1764 pthread_mutex_unlock(&adev->lock);
1765
1766 return ret_uc;
1767 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001768
1769 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001770 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1771 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1772 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1773 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001774 break;
1775 }
1776 }
vivek mehta446c3962015-09-14 10:57:35 -07001777
1778 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1779 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001780}
1781
1782static void free_offload_usecase(struct audio_device *adev,
1783 audio_usecase_t uc_id)
1784{
vivek mehta446c3962015-09-14 10:57:35 -07001785 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001786 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001787
1788 if (!adev->multi_offload_enable)
1789 return;
1790
1791 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1792 if (offload_usecases[offload_uc_index] == uc_id) {
1793 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001794 break;
1795 }
1796 }
1797 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1798}
1799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800static void *offload_thread_loop(void *context)
1801{
1802 struct stream_out *out = (struct stream_out *) context;
1803 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001804 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001806 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1807 set_sched_policy(0, SP_FOREGROUND);
1808 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1809
1810 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001811 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 for (;;) {
1813 struct offload_cmd *cmd = NULL;
1814 stream_callback_event_t event;
1815 bool send_callback = false;
1816
1817 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1818 __func__, list_empty(&out->offload_cmd_list),
1819 out->offload_state);
1820 if (list_empty(&out->offload_cmd_list)) {
1821 ALOGV("%s SLEEPING", __func__);
1822 pthread_cond_wait(&out->offload_cond, &out->lock);
1823 ALOGV("%s RUNNING", __func__);
1824 continue;
1825 }
1826
1827 item = list_head(&out->offload_cmd_list);
1828 cmd = node_to_item(item, struct offload_cmd, node);
1829 list_remove(item);
1830
1831 ALOGVV("%s STATE %d CMD %d out->compr %p",
1832 __func__, out->offload_state, cmd->cmd, out->compr);
1833
1834 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1835 free(cmd);
1836 break;
1837 }
1838
1839 if (out->compr == NULL) {
1840 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001841 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842 pthread_cond_signal(&out->cond);
1843 continue;
1844 }
1845 out->offload_thread_blocked = true;
1846 pthread_mutex_unlock(&out->lock);
1847 send_callback = false;
1848 switch(cmd->cmd) {
1849 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001850 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001852 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001853 send_callback = true;
1854 event = STREAM_CBK_EVENT_WRITE_READY;
1855 break;
1856 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001857 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301858 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001859 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301860 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001861 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301862 if (ret < 0)
1863 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301864 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301865 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001866 compress_drain(out->compr);
1867 else
1868 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301869 if (ret != -ENETRESET) {
1870 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301871 pthread_mutex_lock(&out->lock);
1872 out->send_new_metadata = 1;
1873 out->send_next_track_params = true;
1874 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301875 event = STREAM_CBK_EVENT_DRAIN_READY;
1876 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1877 } else
1878 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 break;
1880 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001881 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001882 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001883 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 send_callback = true;
1885 event = STREAM_CBK_EVENT_DRAIN_READY;
1886 break;
1887 default:
1888 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1889 break;
1890 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001891 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892 out->offload_thread_blocked = false;
1893 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001894 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001895 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001897 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 free(cmd);
1899 }
1900
1901 pthread_cond_signal(&out->cond);
1902 while (!list_empty(&out->offload_cmd_list)) {
1903 item = list_head(&out->offload_cmd_list);
1904 list_remove(item);
1905 free(node_to_item(item, struct offload_cmd, node));
1906 }
1907 pthread_mutex_unlock(&out->lock);
1908
1909 return NULL;
1910}
1911
1912static int create_offload_callback_thread(struct stream_out *out)
1913{
1914 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1915 list_init(&out->offload_cmd_list);
1916 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1917 offload_thread_loop, out);
1918 return 0;
1919}
1920
1921static int destroy_offload_callback_thread(struct stream_out *out)
1922{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001923 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924 stop_compressed_output_l(out);
1925 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1926
1927 pthread_mutex_unlock(&out->lock);
1928 pthread_join(out->offload_thread, (void **) NULL);
1929 pthread_cond_destroy(&out->offload_cond);
1930
1931 return 0;
1932}
1933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934static int stop_output_stream(struct stream_out *out)
1935{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301936 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 struct audio_usecase *uc_info;
1938 struct audio_device *adev = out->dev;
1939
Eric Laurent994a6932013-07-17 11:51:42 -07001940 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001941 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 uc_info = get_usecase_from_list(adev, out->usecase);
1943 if (uc_info == NULL) {
1944 ALOGE("%s: Could not find the usecase (%d) in the list",
1945 __func__, out->usecase);
1946 return -EINVAL;
1947 }
1948
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001949 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301950 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001951 if (adev->visualizer_stop_output != NULL)
1952 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001953
1954 audio_extn_dts_remove_state_notifier_node(out->usecase);
1955
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001956 if (adev->offload_effects_stop_output != NULL)
1957 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1958 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001959
Eric Laurent150dbfe2013-02-27 14:31:02 -08001960 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001961 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962
1963 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001964 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001966 list_remove(&uc_info->list);
1967 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001969 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301970 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001971 ALOGV("Disable passthrough , reset mixer to pcm");
1972 /* NO_PASSTHROUGH */
1973 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001974 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001975 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1976 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001977
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301978 /* Must be called after removing the usecase from list */
1979 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301980 audio_extn_keep_alive_start();
1981
Eric Laurent994a6932013-07-17 11:51:42 -07001982 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 return ret;
1984}
1985
1986int start_output_stream(struct stream_out *out)
1987{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 struct audio_usecase *uc_info;
1990 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301991 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001993 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1994 ret = -EINVAL;
1995 goto error_config;
1996 }
1997
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301998 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1999 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2000 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302001
Naresh Tanniru80659832014-06-04 18:17:56 +05302002 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302003 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302004 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302005 goto error_config;
2006 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302007
Eric Laurentb23d5282013-05-14 15:27:20 -07002008 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 if (out->pcm_device_id < 0) {
2010 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2011 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002012 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002013 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 }
2015
2016 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002017
2018 if (!uc_info) {
2019 ret = -ENOMEM;
2020 goto error_config;
2021 }
2022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 uc_info->id = out->usecase;
2024 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002025 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002026 uc_info->devices = out->devices;
2027 uc_info->in_snd_device = SND_DEVICE_NONE;
2028 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002029 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302031 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2032 adev->perf_lock_opts,
2033 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302034
2035 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2036 audio_extn_keep_alive_stop();
2037 if (audio_extn_passthru_is_enabled() &&
2038 audio_extn_passthru_is_passthrough_stream(out)) {
2039 audio_extn_passthru_on_start(out);
2040 audio_extn_passthru_update_stream_configuration(adev, out);
2041 }
2042 }
2043
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002044 select_devices(adev, out->usecase);
2045
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002046 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2047 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002048 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002049 unsigned int flags = PCM_OUT;
2050 unsigned int pcm_open_retry_count = 0;
2051 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2052 flags |= PCM_MMAP | PCM_NOIRQ;
2053 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002054 } else if (out->realtime) {
2055 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002056 } else
2057 flags |= PCM_MONOTONIC;
2058
2059 while (1) {
2060 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2061 flags, &out->config);
2062 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2063 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2064 if (out->pcm != NULL) {
2065 pcm_close(out->pcm);
2066 out->pcm = NULL;
2067 }
2068 if (pcm_open_retry_count-- == 0) {
2069 ret = -EIO;
2070 goto error_open;
2071 }
2072 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2073 continue;
2074 }
2075 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002077
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 Alamanda8a0f9772015-06-15 10:35:19 -07002080
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002081 ALOGV("%s: pcm_prepare", __func__);
2082 if (pcm_is_ready(out->pcm)) {
2083 ret = pcm_prepare(out->pcm);
2084 if (ret < 0) {
2085 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2086 pcm_close(out->pcm);
2087 out->pcm = NULL;
2088 goto error_open;
2089 }
2090 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002092 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2093 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002095 out->compr = compress_open(adev->snd_card,
2096 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097 COMPRESS_IN, &out->compr_config);
2098 if (out->compr && !is_compress_ready(out->compr)) {
2099 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2100 compress_close(out->compr);
2101 out->compr = NULL;
2102 ret = -EIO;
2103 goto error_open;
2104 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302105 /* compress_open sends params of the track, so reset the flag here */
2106 out->is_compr_metadata_avail = false;
2107
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 if (out->offload_callback)
2109 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002110
Fred Oh3f43e742015-03-04 18:42:34 -08002111 /* Since small bufs uses blocking writes, a write will be blocked
2112 for the default max poll time (20s) in the event of an SSR.
2113 Reduce the poll time to observe and deal with SSR faster.
2114 */
Ashish Jain5106d362016-05-11 19:23:33 +05302115 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002116 compress_set_max_poll_wait(out->compr, 1000);
2117 }
2118
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002119 audio_extn_dts_create_state_notifier_node(out->usecase);
2120 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2121 popcount(out->channel_mask),
2122 out->playback_started);
2123
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002124#ifdef DS1_DOLBY_DDP_ENABLED
2125 if (audio_extn_is_dolby_format(out->format))
2126 audio_extn_dolby_send_ddp_endp_params(adev);
2127#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302128 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 if (adev->visualizer_start_output != NULL)
2130 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2131 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302132 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002133 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002134 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002136
2137 if (ret == 0) {
2138 register_out_stream(out);
2139 if (out->realtime) {
2140 ret = pcm_start(out->pcm);
2141 if (ret < 0)
2142 goto error_open;
2143 }
2144 }
2145
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302146 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002147 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002148
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002149 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302151 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002153error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302154 /*
2155 * sleep 50ms to allow sufficient time for kernel
2156 * drivers to recover incases like SSR.
2157 */
2158 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002159 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160}
2161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162static int check_input_parameters(uint32_t sample_rate,
2163 audio_format_t format,
2164 int channel_count)
2165{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002166 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302168 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2169 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2170 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002171 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302172 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002173
2174 switch (channel_count) {
2175 case 1:
2176 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302177 case 3:
2178 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002179 case 6:
2180 break;
2181 default:
2182 ret = -EINVAL;
2183 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184
2185 switch (sample_rate) {
2186 case 8000:
2187 case 11025:
2188 case 12000:
2189 case 16000:
2190 case 22050:
2191 case 24000:
2192 case 32000:
2193 case 44100:
2194 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302195 case 96000:
2196 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 break;
2198 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002199 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 }
2201
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002202 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203}
2204
2205static size_t get_input_buffer_size(uint32_t sample_rate,
2206 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002207 int channel_count,
2208 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209{
2210 size_t size = 0;
2211
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002212 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2213 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002215 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002216 if (is_low_latency)
2217 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302218
2219 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002221 /* make sure the size is multiple of 32 bytes
2222 * At 48 kHz mono 16-bit PCM:
2223 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2224 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2225 */
2226 size += 0x1f;
2227 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002228
2229 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230}
2231
Ashish Jain5106d362016-05-11 19:23:33 +05302232static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2233{
2234 uint64_t actual_frames_rendered = 0;
2235 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2236
2237 /* This adjustment accounts for buffering after app processor.
2238 * It is based on estimated DSP latency per use case, rather than exact.
2239 */
2240 int64_t platform_latency = platform_render_latency(out->usecase) *
2241 out->sample_rate / 1000000LL;
2242
2243 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2244 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2245 * hence only estimate.
2246 */
2247 int64_t signed_frames = out->written - kernel_buffer_size;
2248
2249 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2250
2251 if (signed_frames > 0)
2252 actual_frames_rendered = signed_frames;
2253
2254 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2255 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2256 (long long int)out->written, (int)kernel_buffer_size,
2257 audio_bytes_per_sample(out->compr_config.codec->format),
2258 popcount(out->channel_mask));
2259
2260 return actual_frames_rendered;
2261}
2262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2264{
2265 struct stream_out *out = (struct stream_out *)stream;
2266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268}
2269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002270static int out_set_sample_rate(struct audio_stream *stream __unused,
2271 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272{
2273 return -ENOSYS;
2274}
2275
2276static size_t out_get_buffer_size(const struct audio_stream *stream)
2277{
2278 struct stream_out *out = (struct stream_out *)stream;
2279
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002280 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002282 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2283 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302284 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302285 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002287 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002288 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289}
2290
2291static uint32_t out_get_channels(const struct audio_stream *stream)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294
2295 return out->channel_mask;
2296}
2297
2298static audio_format_t out_get_format(const struct audio_stream *stream)
2299{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 struct stream_out *out = (struct stream_out *)stream;
2301
2302 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303}
2304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002305static int out_set_format(struct audio_stream *stream __unused,
2306 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307{
2308 return -ENOSYS;
2309}
2310
2311static int out_standby(struct audio_stream *stream)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302316 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2317 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002319 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002321 if (adev->adm_deregister_stream)
2322 adev->adm_deregister_stream(adev->adm_data, out->handle);
2323
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002324 if (is_offload_usecase(out->usecase))
2325 stop_compressed_output_l(out);
2326
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002327 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002329 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2330 voice_extn_compress_voip_close_output_stream(stream);
2331 pthread_mutex_unlock(&adev->lock);
2332 pthread_mutex_unlock(&out->lock);
2333 ALOGD("VOIP output entered standby");
2334 return 0;
2335 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 if (out->pcm) {
2337 pcm_close(out->pcm);
2338 out->pcm = NULL;
2339 }
2340 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002341 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302342 out->send_next_track_params = false;
2343 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002344 out->gapless_mdata.encoder_delay = 0;
2345 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 if (out->compr != NULL) {
2347 compress_close(out->compr);
2348 out->compr = NULL;
2349 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002350 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002352 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 }
2354 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302355 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 return 0;
2357}
2358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002359static int out_dump(const struct audio_stream *stream __unused,
2360 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361{
2362 return 0;
2363}
2364
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002365static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2366{
2367 int ret = 0;
2368 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002369
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002371 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002372 return -EINVAL;
2373 }
2374
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302375 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002376
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002377 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2378 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302379 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002380 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002381 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2382 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302383 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002384 }
2385
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002386 ALOGV("%s new encoder delay %u and padding %u", __func__,
2387 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2388
2389 return 0;
2390}
2391
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002392static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2393{
2394 return out == adev->primary_output || out == adev->voice_tx_output;
2395}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2398{
2399 struct stream_out *out = (struct stream_out *)stream;
2400 struct audio_device *adev = out->dev;
2401 struct str_parms *parms;
2402 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002403 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404
sangwoobc677242013-08-08 16:53:43 +09002405 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002406 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302408 if (!parms)
2409 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002410 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2411 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002413 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002414 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002416 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002417 * When HDMI cable is unplugged the music playback is paused and
2418 * the policy manager sends routing=0. But the audioflinger continues
2419 * to write data until standby time (3sec). As the HDMI core is
2420 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002421 * Avoid this by routing audio to speaker until standby.
2422 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002423 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2424 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302425 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002426 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2427 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002428 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302429 /*
2430 * When A2DP is disconnected the
2431 * music playback is paused and the policy manager sends routing=0
2432 * But the audioflingercontinues to write data until standby time
2433 * (3sec). As BT is turned off, the write gets blocked.
2434 * Avoid this by routing audio to speaker until standby.
2435 */
2436 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2437 (val == AUDIO_DEVICE_NONE)) {
2438 val = AUDIO_DEVICE_OUT_SPEAKER;
2439 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002440
2441 /*
2442 * select_devices() call below switches all the usecases on the same
2443 * backend to the new device. Refer to check_usecases_codec_backend() in
2444 * the select_devices(). But how do we undo this?
2445 *
2446 * For example, music playback is active on headset (deep-buffer usecase)
2447 * and if we go to ringtones and select a ringtone, low-latency usecase
2448 * will be started on headset+speaker. As we can't enable headset+speaker
2449 * and headset devices at the same time, select_devices() switches the music
2450 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2451 * So when the ringtone playback is completed, how do we undo the same?
2452 *
2453 * We are relying on the out_set_parameters() call on deep-buffer output,
2454 * once the ringtone playback is ended.
2455 * NOTE: We should not check if the current devices are same as new devices.
2456 * Because select_devices() must be called to switch back the music
2457 * playback to headset.
2458 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002459 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002460 audio_devices_t new_dev = val;
2461 bool same_dev = out->devices == new_dev;
2462 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002463
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002464 if (output_drives_call(adev, out)) {
2465 if(!voice_is_in_call(adev)) {
2466 if (adev->mode == AUDIO_MODE_IN_CALL) {
2467 adev->current_call_output = out;
2468 ret = voice_start_call(adev);
2469 }
2470 } else {
2471 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002472 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002473 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002474 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002475
2476 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002477 if (!same_dev) {
2478 ALOGV("update routing change");
2479 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302480 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2481 adev->perf_lock_opts,
2482 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002483 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002484 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302485 if (!same_dev)
2486 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002487 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002488 }
2489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002491 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002493
2494 if (out == adev->primary_output) {
2495 pthread_mutex_lock(&adev->lock);
2496 audio_extn_set_parameters(adev, parms);
2497 pthread_mutex_unlock(&adev->lock);
2498 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002499 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002500 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002501 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002502
2503 audio_extn_dts_create_state_notifier_node(out->usecase);
2504 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2505 popcount(out->channel_mask),
2506 out->playback_started);
2507
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002508 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002509 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302512error:
Eric Laurent994a6932013-07-17 11:51:42 -07002513 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 return ret;
2515}
2516
2517static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2518{
2519 struct stream_out *out = (struct stream_out *)stream;
2520 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002521 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 char value[256];
2523 struct str_parms *reply = str_parms_create();
2524 size_t i, j;
2525 int ret;
2526 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002527
2528 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002529 if (reply) {
2530 str_parms_destroy(reply);
2531 }
2532 if (query) {
2533 str_parms_destroy(query);
2534 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002535 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2536 return NULL;
2537 }
2538
Eric Laurent994a6932013-07-17 11:51:42 -07002539 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2541 if (ret >= 0) {
2542 value[0] = '\0';
2543 i = 0;
2544 while (out->supported_channel_masks[i] != 0) {
2545 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2546 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2547 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002548 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002550 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 first = false;
2552 break;
2553 }
2554 }
2555 i++;
2556 }
2557 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2558 str = str_parms_to_str(reply);
2559 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002560 voice_extn_out_get_parameters(out, query, reply);
2561 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002562 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002563 free(str);
2564 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002567
Alexy Joseph62142aa2015-11-16 15:10:34 -08002568
2569 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2570 if (ret >= 0) {
2571 value[0] = '\0';
2572 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2573 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302574 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002575 } else {
2576 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302577 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002578 }
2579 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002580 if (str)
2581 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002582 str = str_parms_to_str(reply);
2583 }
2584
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002585 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2586 if (ret >= 0) {
2587 value[0] = '\0';
2588 i = 0;
2589 first = true;
2590 while (out->supported_formats[i] != 0) {
2591 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2592 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2593 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002594 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002595 }
2596 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2597 first = false;
2598 break;
2599 }
2600 }
2601 i++;
2602 }
2603 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002604 if (str)
2605 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002606 str = str_parms_to_str(reply);
2607 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002608
2609 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2610 if (ret >= 0) {
2611 value[0] = '\0';
2612 i = 0;
2613 first = true;
2614 while (out->supported_sample_rates[i] != 0) {
2615 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2616 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2617 if (!first) {
2618 strlcat(value, "|", sizeof(value));
2619 }
2620 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2621 first = false;
2622 break;
2623 }
2624 }
2625 i++;
2626 }
2627 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2628 if (str)
2629 free(str);
2630 str = str_parms_to_str(reply);
2631 }
2632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 str_parms_destroy(query);
2634 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002635 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 return str;
2637}
2638
2639static uint32_t out_get_latency(const struct audio_stream_out *stream)
2640{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002641 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002643 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644
Alexy Josephaa54c872014-12-03 02:46:47 -08002645 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002646 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002647 } else if (out->realtime) {
2648 // since the buffer won't be filled up faster than realtime,
2649 // return a smaller number
2650 if (out->config.rate)
2651 period_ms = (out->af_period_multiplier * out->config.period_size *
2652 1000) / (out->config.rate);
2653 else
2654 period_ms = 0;
2655 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002656 } else {
2657 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002659 }
2660
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302661 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002662 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663}
2664
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302665static float AmpToDb(float amplification)
2666{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302667 float db = DSD_VOLUME_MIN_DB;
2668 if (amplification > 0) {
2669 db = 20 * log10(amplification);
2670 if(db < DSD_VOLUME_MIN_DB)
2671 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302672 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302673 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302674}
2675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676static int out_set_volume(struct audio_stream_out *stream, float left,
2677 float right)
2678{
Eric Laurenta9024de2013-04-04 09:19:12 -07002679 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 int volume[2];
2681
Eric Laurenta9024de2013-04-04 09:19:12 -07002682 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2683 /* only take left channel into account: the API is for stereo anyway */
2684 out->muted = (left == 0.0f);
2685 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002686 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302687 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002688 /*
2689 * Set mute or umute on HDMI passthrough stream.
2690 * Only take left channel into account.
2691 * Mute is 0 and unmute 1
2692 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302693 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302694 } else if (out->format == AUDIO_FORMAT_DSD){
2695 char mixer_ctl_name[128] = "DSD Volume";
2696 struct audio_device *adev = out->dev;
2697 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2698
2699 if (!ctl) {
2700 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2701 __func__, mixer_ctl_name);
2702 return -EINVAL;
2703 }
2704 volume[0] = (int)(AmpToDb(left));
2705 volume[1] = (int)(AmpToDb(right));
2706 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2707 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002708 } else {
2709 char mixer_ctl_name[128];
2710 struct audio_device *adev = out->dev;
2711 struct mixer_ctl *ctl;
2712 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002713 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002715 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2716 "Compress Playback %d Volume", pcm_device_id);
2717 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2718 if (!ctl) {
2719 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2720 __func__, mixer_ctl_name);
2721 return -EINVAL;
2722 }
2723 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2724 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2725 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2726 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002727 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002728 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 return -ENOSYS;
2731}
2732
2733static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2734 size_t bytes)
2735{
2736 struct stream_out *out = (struct stream_out *)stream;
2737 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302738 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002739 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002741 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302742
Naresh Tanniru80659832014-06-04 18:17:56 +05302743 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002744
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302745 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302746 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302747 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2748 pthread_mutex_unlock(&out->lock);
2749 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302750 } else {
2751 /* increase written size during SSR to avoid mismatch
2752 * with the written frames count in AF
2753 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002754 // bytes per frame
2755 size_t bpf = audio_bytes_per_sample(out->format) *
2756 audio_channel_count_from_out_mask(out->channel_mask);
2757 if (bpf != 0)
2758 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302759 ALOGD(" %s: sound card is not active/SSR state", __func__);
2760 ret= -EIO;
2761 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302762 }
2763 }
2764
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302765 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302766 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2767 if (audio_bytes_per_sample(out->format) != 0)
2768 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2769 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302770 goto exit;
2771 }
2772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002774 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002775 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002776 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2777 ret = voice_extn_compress_voip_start_output_stream(out);
2778 else
2779 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002780 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002783 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 goto exit;
2785 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002786
2787 if (last_known_cal_step != -1) {
2788 ALOGD("%s: retry previous failed cal level set", __func__);
2789 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792
Ashish Jain81eb2a82015-05-13 10:52:34 +05302793 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002794 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302795 adev->is_channel_status_set = true;
2796 }
2797
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002798 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002799 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002800 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002801 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002802 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2803 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302804 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2805 ALOGD("copl(%p):send next track params in gapless", out);
2806 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2807 out->send_next_track_params = false;
2808 out->is_compr_metadata_avail = false;
2809 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002810 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302811 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302812 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002813
Ashish Jain83a6cc22016-06-28 14:34:17 +05302814 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302815 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302816 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302817 pthread_mutex_unlock(&out->lock);
2818 return -EINVAL;
2819 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302820 audio_format_t dst_format = out->hal_op_format;
2821 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302822
2823 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2824 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2825
Ashish Jain83a6cc22016-06-28 14:34:17 +05302826 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302827 dst_format,
2828 buffer,
2829 src_format,
2830 frames);
2831
Ashish Jain83a6cc22016-06-28 14:34:17 +05302832 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302833 bytes_to_write);
2834
2835 /*Convert written bytes in audio flinger format*/
2836 if (ret > 0)
2837 ret = ((ret * format_to_bitwidth_table[out->format]) /
2838 format_to_bitwidth_table[dst_format]);
2839 }
2840 } else
2841 ret = compress_write(out->compr, buffer, bytes);
2842
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302843 if (ret < 0)
2844 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302845 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302846 /*msg to cb thread only if non blocking write is enabled*/
2847 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302848 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302850 } else if (-ENETRESET == ret) {
2851 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2852 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2853 pthread_mutex_unlock(&out->lock);
2854 out_standby(&out->stream.common);
2855 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 }
Ashish Jain5106d362016-05-11 19:23:33 +05302857 if ( ret == (ssize_t)bytes && !out->non_blocking)
2858 out->written += bytes;
2859
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302860 /* Call compr start only when non-zero bytes of data is there to be rendered */
2861 if (!out->playback_started && ret > 0) {
2862 int status = compress_start(out->compr);
2863 if (status < 0) {
2864 ret = status;
2865 ALOGE("%s: compr start failed with err %d", __func__, errno);
2866 goto exit;
2867 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002868 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 out->playback_started = 1;
2870 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002871
2872 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2873 popcount(out->channel_mask),
2874 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 }
2876 pthread_mutex_unlock(&out->lock);
2877 return ret;
2878 } else {
2879 if (out->pcm) {
2880 if (out->muted)
2881 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002882
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302883 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002884
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002885 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002886
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002887 if (out->config.rate)
2888 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2889 out->config.rate;
2890
2891 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2892
2893 request_out_focus(out, ns);
2894
2895 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002896 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002897 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302898 out->convert_buffer != NULL) {
2899
2900 memcpy_by_audio_format(out->convert_buffer,
2901 out->hal_op_format,
2902 buffer,
2903 out->hal_ip_format,
2904 out->config.period_size * out->config.channels);
2905
2906 ret = pcm_write(out->pcm, out->convert_buffer,
2907 (out->config.period_size *
2908 out->config.channels *
2909 format_to_bitwidth_table[out->hal_op_format]));
2910 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002911 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302912 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002913
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002914 release_out_focus(out);
2915
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302916 if (ret < 0)
2917 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302918 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2919 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2920 else
2921 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 }
2924
2925exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302926 /* ToDo: There may be a corner case when SSR happens back to back during
2927 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302928 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302929 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302930 }
2931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 pthread_mutex_unlock(&out->lock);
2933
2934 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002935 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002936 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302937 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302938 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302939 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302940 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302941 out->standby = true;
2942 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302944 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2945 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2946 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947 }
2948 return bytes;
2949}
2950
2951static int out_get_render_position(const struct audio_stream_out *stream,
2952 uint32_t *dsp_frames)
2953{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302955 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002956
2957 if (dsp_frames == NULL)
2958 return -EINVAL;
2959
2960 *dsp_frames = 0;
2961 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002962 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302963
2964 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2965 * this operation and adev_close_output_stream(where out gets reset).
2966 */
2967 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2968 *dsp_frames = get_actual_pcm_frames_rendered(out);
2969 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2970 return 0;
2971 }
2972
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002973 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302974 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302975 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002976 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302977 if (ret < 0)
2978 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302980 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981 }
2982 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302983 if (-ENETRESET == ret) {
2984 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2985 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2986 return -EINVAL;
2987 } else if(ret < 0) {
2988 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2989 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302990 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2991 /*
2992 * Handle corner case where compress session is closed during SSR
2993 * and timestamp is queried
2994 */
2995 ALOGE(" ERROR: sound card not active, return error");
2996 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302997 } else {
2998 return 0;
2999 }
Zhou Song32a556e2015-05-05 10:46:56 +08003000 } else if (audio_is_linear_pcm(out->format)) {
3001 *dsp_frames = out->written;
3002 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 } else
3004 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005}
3006
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003007static int out_add_audio_effect(const struct audio_stream *stream __unused,
3008 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009{
3010 return 0;
3011}
3012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003013static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3014 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015{
3016 return 0;
3017}
3018
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003019static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3020 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021{
3022 return -EINVAL;
3023}
3024
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003025static int out_get_presentation_position(const struct audio_stream_out *stream,
3026 uint64_t *frames, struct timespec *timestamp)
3027{
3028 struct stream_out *out = (struct stream_out *)stream;
3029 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003030 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003031
Ashish Jain5106d362016-05-11 19:23:33 +05303032 /* below piece of code is not guarded against any lock because audioFliner serializes
3033 * this operation and adev_close_output_stream( where out gets reset).
3034 */
3035 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3036 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3037 *frames = get_actual_pcm_frames_rendered(out);
3038 /* this is the best we can do */
3039 clock_gettime(CLOCK_MONOTONIC, timestamp);
3040 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3041 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3042 return 0;
3043 }
3044
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003045 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003046
Ashish Jain5106d362016-05-11 19:23:33 +05303047 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3048 ret = compress_get_tstamp(out->compr, &dsp_frames,
3049 &out->sample_rate);
3050 ALOGVV("%s rendered frames %ld sample_rate %d",
3051 __func__, dsp_frames, out->sample_rate);
3052 *frames = dsp_frames;
3053 if (ret < 0)
3054 ret = -errno;
3055 if (-ENETRESET == ret) {
3056 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3057 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3058 ret = -EINVAL;
3059 } else
3060 ret = 0;
3061 /* this is the best we can do */
3062 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003063 } else {
3064 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003065 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003066 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3067 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003068 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003069 // This adjustment accounts for buffering after app processor.
3070 // It is based on estimated DSP latency per use case, rather than exact.
3071 signed_frames -=
3072 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3073
Eric Laurent949a0892013-09-20 09:20:13 -07003074 // It would be unusual for this value to be negative, but check just in case ...
3075 if (signed_frames >= 0) {
3076 *frames = signed_frames;
3077 ret = 0;
3078 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003079 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303080 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3081 *frames = out->written;
3082 clock_gettime(CLOCK_MONOTONIC, timestamp);
3083 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003084 }
3085 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003086 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003087 return ret;
3088}
3089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090static int out_set_callback(struct audio_stream_out *stream,
3091 stream_callback_t callback, void *cookie)
3092{
3093 struct stream_out *out = (struct stream_out *)stream;
3094
3095 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003096 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 out->offload_callback = callback;
3098 out->offload_cookie = cookie;
3099 pthread_mutex_unlock(&out->lock);
3100 return 0;
3101}
3102
3103static int out_pause(struct audio_stream_out* stream)
3104{
3105 struct stream_out *out = (struct stream_out *)stream;
3106 int status = -ENOSYS;
3107 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003108 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003109 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003110 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303112 struct audio_device *adev = out->dev;
3113 int snd_scard_state = get_snd_card_state(adev);
3114
3115 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3116 status = compress_pause(out->compr);
3117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003119
Mingming Yin21854652016-04-13 11:54:02 -07003120 if (audio_extn_passthru_is_active()) {
3121 ALOGV("offload use case, pause passthru");
3122 audio_extn_passthru_on_pause(out);
3123 }
3124
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303125 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003126 audio_extn_dts_notify_playback_state(out->usecase, 0,
3127 out->sample_rate, popcount(out->channel_mask),
3128 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 }
3130 pthread_mutex_unlock(&out->lock);
3131 }
3132 return status;
3133}
3134
3135static int out_resume(struct audio_stream_out* stream)
3136{
3137 struct stream_out *out = (struct stream_out *)stream;
3138 int status = -ENOSYS;
3139 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003140 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003141 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003143 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 struct audio_device *adev = out->dev;
3146 int snd_scard_state = get_snd_card_state(adev);
3147
Mingming Yin21854652016-04-13 11:54:02 -07003148 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3149 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3150 pthread_mutex_lock(&out->dev->lock);
3151 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003152 pthread_mutex_unlock(&out->dev->lock);
3153 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303154 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003155 }
3156 if (!status) {
3157 out->offload_state = OFFLOAD_STATE_PLAYING;
3158 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303159 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003160 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3161 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003162 }
3163 pthread_mutex_unlock(&out->lock);
3164 }
3165 return status;
3166}
3167
3168static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3169{
3170 struct stream_out *out = (struct stream_out *)stream;
3171 int status = -ENOSYS;
3172 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003173 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003174 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003175 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3176 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3177 else
3178 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3179 pthread_mutex_unlock(&out->lock);
3180 }
3181 return status;
3182}
3183
3184static int out_flush(struct audio_stream_out* stream)
3185{
3186 struct stream_out *out = (struct stream_out *)stream;
3187 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003188 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003189 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003190 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003191 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3192 stop_compressed_output_l(out);
3193 out->written = 0;
3194 } else {
3195 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3196 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003198 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 return 0;
3200 }
3201 return -ENOSYS;
3202}
3203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204/** audio_stream_in implementation **/
3205static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3206{
3207 struct stream_in *in = (struct stream_in *)stream;
3208
3209 return in->config.rate;
3210}
3211
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003212static int in_set_sample_rate(struct audio_stream *stream __unused,
3213 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214{
3215 return -ENOSYS;
3216}
3217
3218static size_t in_get_buffer_size(const struct audio_stream *stream)
3219{
3220 struct stream_in *in = (struct stream_in *)stream;
3221
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003222 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3223 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003224 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3225 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003227 return in->config.period_size * in->af_period_multiplier *
3228 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229}
3230
3231static uint32_t in_get_channels(const struct audio_stream *stream)
3232{
3233 struct stream_in *in = (struct stream_in *)stream;
3234
3235 return in->channel_mask;
3236}
3237
3238static audio_format_t in_get_format(const struct audio_stream *stream)
3239{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003240 struct stream_in *in = (struct stream_in *)stream;
3241
3242 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243}
3244
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003245static int in_set_format(struct audio_stream *stream __unused,
3246 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247{
3248 return -ENOSYS;
3249}
3250
3251static int in_standby(struct audio_stream *stream)
3252{
3253 struct stream_in *in = (struct stream_in *)stream;
3254 struct audio_device *adev = in->dev;
3255 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303256 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3257 stream, in->usecase, use_case_table[in->usecase]);
3258
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003259 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003260 if (!in->standby && in->is_st_session) {
3261 ALOGD("%s: sound trigger pcm stop lab", __func__);
3262 audio_extn_sound_trigger_stop_lab(in);
3263 in->standby = 1;
3264 }
3265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003267 if (adev->adm_deregister_stream)
3268 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3269
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003270 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003272 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3273 voice_extn_compress_voip_close_input_stream(stream);
3274 ALOGD("VOIP input entered standby");
3275 } else {
3276 if (in->pcm) {
3277 pcm_close(in->pcm);
3278 in->pcm = NULL;
3279 }
3280 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003281 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003282 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 }
3284 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003285 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 return status;
3287}
3288
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003289static int in_dump(const struct audio_stream *stream __unused,
3290 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291{
3292 return 0;
3293}
3294
3295static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3296{
3297 struct stream_in *in = (struct stream_in *)stream;
3298 struct audio_device *adev = in->dev;
3299 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003301 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303303 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 parms = str_parms_create_str(kvpairs);
3305
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303306 if (!parms)
3307 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003308 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003309 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003310
3311 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3312 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 val = atoi(value);
3314 /* no audio source uses val == 0 */
3315 if ((in->source != val) && (val != 0)) {
3316 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003317 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3318 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3319 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003320 (in->config.rate == 8000 || in->config.rate == 16000 ||
3321 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003322 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003323 err = voice_extn_compress_voip_open_input_stream(in);
3324 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003325 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003326 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003327 }
3328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 }
3330 }
3331
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003332 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3333 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 in->device = val;
3337 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003338 if (!in->standby && !in->is_st_session) {
3339 ALOGV("update input routing change");
3340 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003341 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 }
3344 }
3345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003347 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
3349 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303350error:
Eric Laurent994a6932013-07-17 11:51:42 -07003351 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 return ret;
3353}
3354
3355static char* in_get_parameters(const struct audio_stream *stream,
3356 const char *keys)
3357{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003358 struct stream_in *in = (struct stream_in *)stream;
3359 struct str_parms *query = str_parms_create_str(keys);
3360 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003362
3363 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003364 if (reply) {
3365 str_parms_destroy(reply);
3366 }
3367 if (query) {
3368 str_parms_destroy(query);
3369 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003370 ALOGE("in_get_parameters: failed to create query or reply");
3371 return NULL;
3372 }
3373
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003374 ALOGV("%s: enter: keys - %s", __func__, keys);
3375
3376 voice_extn_in_get_parameters(in, query, reply);
3377
3378 str = str_parms_to_str(reply);
3379 str_parms_destroy(query);
3380 str_parms_destroy(reply);
3381
3382 ALOGV("%s: exit: returns - %s", __func__, str);
3383 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384}
3385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003386static int in_set_gain(struct audio_stream_in *stream __unused,
3387 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388{
3389 return 0;
3390}
3391
3392static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3393 size_t bytes)
3394{
3395 struct stream_in *in = (struct stream_in *)stream;
3396 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303397 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303398 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303399 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003401 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303402
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003403 if (in->is_st_session) {
3404 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3405 /* Read from sound trigger HAL */
3406 audio_extn_sound_trigger_read(in, buffer, bytes);
3407 pthread_mutex_unlock(&in->lock);
3408 return bytes;
3409 }
3410
Ashish Jainbbce4322016-02-16 13:25:27 +05303411 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003412 ALOGD(" %s: sound card is not active/SSR state", __func__);
3413 ret= -EIO;;
3414 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303415 }
3416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003418 pthread_mutex_lock(&adev->lock);
3419 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3420 ret = voice_extn_compress_voip_start_input_stream(in);
3421 else
3422 ret = start_input_stream(in);
3423 pthread_mutex_unlock(&adev->lock);
3424 if (ret != 0) {
3425 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 }
3427 in->standby = 0;
3428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003430 // what's the duration requested by the client?
3431 long ns = 0;
3432
3433 if (in->config.rate)
3434 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3435 in->config.rate;
3436
3437 request_in_focus(in, ns);
3438 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303441 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003442 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303443 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003444 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003445 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003446 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303447 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003448 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303449 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3450 if (bytes % 4 == 0) {
3451 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3452 int_buf_stream = buffer;
3453 for (size_t itt=0; itt < bytes/4 ; itt++) {
3454 int_buf_stream[itt] >>= 8;
3455 }
3456 } else {
3457 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3458 ret = -EINVAL;
3459 goto exit;
3460 }
3461 } if (ret < 0) {
3462 ret = -errno;
3463 }
3464 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 }
3466
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003467 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 /*
3470 * Instead of writing zeroes here, we could trust the hardware
3471 * to always provide zeroes when muted.
3472 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303473 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3474 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 memset(buffer, 0, bytes);
3476
3477exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303478 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303479 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003480 if (-ENETRESET == ret)
3481 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 pthread_mutex_unlock(&in->lock);
3484
3485 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303486 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303487 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303488 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303489 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303490 in->standby = true;
3491 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303492 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003494 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303495 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303496 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 }
3498 return bytes;
3499}
3500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003501static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502{
3503 return 0;
3504}
3505
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003506static int add_remove_audio_effect(const struct audio_stream *stream,
3507 effect_handle_t effect,
3508 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003510 struct stream_in *in = (struct stream_in *)stream;
3511 int status = 0;
3512 effect_descriptor_t desc;
3513
3514 status = (*effect)->get_descriptor(effect, &desc);
3515 if (status != 0)
3516 return status;
3517
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003518 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003519 pthread_mutex_lock(&in->dev->lock);
3520 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3521 in->enable_aec != enable &&
3522 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3523 in->enable_aec = enable;
3524 if (!in->standby)
3525 select_devices(in->dev, in->usecase);
3526 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003527 if (in->enable_ns != enable &&
3528 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3529 in->enable_ns = enable;
3530 if (!in->standby)
3531 select_devices(in->dev, in->usecase);
3532 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003533 pthread_mutex_unlock(&in->dev->lock);
3534 pthread_mutex_unlock(&in->lock);
3535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 return 0;
3537}
3538
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003539static int in_add_audio_effect(const struct audio_stream *stream,
3540 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541{
Eric Laurent994a6932013-07-17 11:51:42 -07003542 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003543 return add_remove_audio_effect(stream, effect, true);
3544}
3545
3546static int in_remove_audio_effect(const struct audio_stream *stream,
3547 effect_handle_t effect)
3548{
Eric Laurent994a6932013-07-17 11:51:42 -07003549 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003550 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551}
3552
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303553int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 audio_io_handle_t handle,
3555 audio_devices_t devices,
3556 audio_output_flags_t flags,
3557 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003558 struct audio_stream_out **stream_out,
3559 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560{
3561 struct audio_device *adev = (struct audio_device *)dev;
3562 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303563 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003564 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303567
3568 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3569 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003570 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303571 return -EINVAL;
3572 }
3573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3575
Mingming Yin3a941d42016-02-17 18:08:05 -08003576 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3577 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303578 devices, flags, &out->stream);
3579
3580
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003581 if (!out) {
3582 return -ENOMEM;
3583 }
3584
Haynes Mathew George204045b2015-02-25 20:32:03 -08003585 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003586 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003587 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 if (devices == AUDIO_DEVICE_NONE)
3590 devices = AUDIO_DEVICE_OUT_SPEAKER;
3591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 out->flags = flags;
3593 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003594 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003595 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 out->sample_rate = config->sample_rate;
3597 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3598 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003599 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003600 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003601 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303602 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603
Mingming Yin3a941d42016-02-17 18:08:05 -08003604 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3605 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3606 pthread_mutex_lock(&adev->lock);
3607 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3608 ret = read_hdmi_sink_caps(out);
3609 pthread_mutex_unlock(&adev->lock);
3610 if (ret != 0) {
3611 if (ret == -ENOSYS) {
3612 /* ignore and go with default */
3613 ret = 0;
3614 } else {
3615 ALOGE("error reading hdmi sink caps");
3616 goto error_open;
3617 }
3618 }
3619 }
3620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003622 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303623 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3624 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003625 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3626 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3627
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003628 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003629 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3630 /*
3631 * Do not handle stereo output in Multi-channel cases
3632 * Stereo case is handled in normal playback path
3633 */
3634 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3635 ret = AUDIO_CHANNEL_OUT_STEREO;
3636 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003637
3638 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3639 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003640 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003641 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003642 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003643
3644 if (config->sample_rate == 0)
3645 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3646 if (config->channel_mask == 0)
3647 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003648 if (config->format == 0)
3649 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003650
3651 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003653 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3655 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003657 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003659 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3660 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003661 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003662 ret = voice_extn_compress_voip_open_output_stream(out);
3663 if (ret != 0) {
3664 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3665 __func__, ret);
3666 goto error_open;
3667 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003668 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3669 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3672 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3673 ALOGE("%s: Unsupported Offload information", __func__);
3674 ret = -EINVAL;
3675 goto error_open;
3676 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003677
Mingming Yin3a941d42016-02-17 18:08:05 -08003678 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003679 if(config->offload_info.format == 0)
3680 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003681 if (config->offload_info.sample_rate == 0)
3682 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003683 }
3684
Mingming Yin90310102013-11-13 16:57:00 -08003685 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303686 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003687 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 ret = -EINVAL;
3689 goto error_open;
3690 }
3691
3692 out->compr_config.codec = (struct snd_codec *)
3693 calloc(1, sizeof(struct snd_codec));
3694
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003695 if (!out->compr_config.codec) {
3696 ret = -ENOMEM;
3697 goto error_open;
3698 }
3699
vivek mehta0ea887a2015-08-26 14:01:20 -07003700 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303701 out->stream.pause = out_pause;
3702 out->stream.flush = out_flush;
3703 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003704 out->usecase = get_offload_usecase(adev, true);
3705 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003706 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003707 out->stream.set_callback = out_set_callback;
3708 out->stream.pause = out_pause;
3709 out->stream.resume = out_resume;
3710 out->stream.drain = out_drain;
3711 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003712 out->usecase = get_offload_usecase(adev, false);
3713 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003714 }
vivek mehta446c3962015-09-14 10:57:35 -07003715
3716 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003717 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3718 config->format == 0 && config->sample_rate == 0 &&
3719 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003720 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003721 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3722 } else {
3723 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3724 ret = -EEXIST;
3725 goto error_open;
3726 }
vivek mehta446c3962015-09-14 10:57:35 -07003727 }
3728
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003729 if (config->offload_info.channel_mask)
3730 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003731 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003732 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003733 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003734 } else {
3735 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3736 ret = -EINVAL;
3737 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003738 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003739
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003740 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003741 out->sample_rate = config->offload_info.sample_rate;
3742
Mingming Yin3ee55c62014-08-04 14:23:35 -07003743 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003744
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303745 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3746 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3747 audio_extn_dolby_send_ddp_endp_params(adev);
3748 audio_extn_dolby_set_dmid(adev);
3749 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003750
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003751 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003752 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003753 out->compr_config.codec->bit_rate =
3754 config->offload_info.bit_rate;
3755 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303756 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303758 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003759 /*TODO: Do we need to change it for passthrough */
3760 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003761
Manish Dewangana6fc5442015-08-24 20:30:31 +05303762 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3763 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3764 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3765 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303766
3767 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3768 AUDIO_FORMAT_PCM) {
3769
3770 /*Based on platform support, configure appropriate alsa format for corresponding
3771 *hal input format.
3772 */
3773 out->compr_config.codec->format = hal_format_to_alsa(
3774 config->offload_info.format);
3775
Ashish Jain83a6cc22016-06-28 14:34:17 +05303776 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303777 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303778 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303779
3780 /*for direct PCM playback populate bit_width based on selected alsa format as
3781 *hal input format and alsa format might differ based on platform support.
3782 */
3783 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303784 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303785
3786 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3787
3788 /* Check if alsa session is configured with the same format as HAL input format,
3789 * if not then derive correct fragment size needed to accomodate the
3790 * conversion of HAL input format to alsa format.
3791 */
3792 audio_extn_utils_update_direct_pcm_fragment_size(out);
3793
3794 /*if hal input and output fragment size is different this indicates HAL input format is
3795 *not same as the alsa format
3796 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303797 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303798 /*Allocate a buffer to convert input data to the alsa configured format.
3799 *size of convert buffer is equal to the size required to hold one fragment size
3800 *worth of pcm data, this is because flinger does not write more than fragment_size
3801 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303802 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3803 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303804 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3805 ret = -ENOMEM;
3806 goto error_open;
3807 }
3808 }
3809 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3810 out->compr_config.fragment_size =
3811 audio_extn_passthru_get_buffer_size(&config->offload_info);
3812 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3813 } else {
3814 out->compr_config.fragment_size =
3815 platform_get_compress_offload_buffer_size(&config->offload_info);
3816 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3817 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003818
Amit Shekhar6f461b12014-08-01 14:52:58 -07003819 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303820 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3823 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003824
Alexy Josephaa54c872014-12-03 02:46:47 -08003825
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003826 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303827 out->send_next_track_params = false;
3828 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003829 out->offload_state = OFFLOAD_STATE_IDLE;
3830 out->playback_started = 0;
3831
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003832 audio_extn_dts_create_state_notifier_node(out->usecase);
3833
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003834 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3835 __func__, config->offload_info.version,
3836 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303837
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303838 /* Check if DSD audio format is supported in codec
3839 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303840 */
3841
3842 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303843 (!platform_check_codec_dsd_support(adev->platform) ||
3844 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303845 ret = -EINVAL;
3846 goto error_open;
3847 }
3848
Ashish Jain5106d362016-05-11 19:23:33 +05303849 /* Disable gapless if any of the following is true
3850 * passthrough playback
3851 * AV playback
3852 * Direct PCM playback
3853 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303854 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303855 (config->format == AUDIO_FORMAT_DSD) ||
3856 config->offload_info.has_video ||
3857 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303858 check_and_set_gapless_mode(adev, false);
3859 } else
3860 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003861
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303862 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003863 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3864 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303865 if (config->format == AUDIO_FORMAT_DSD) {
3866 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3867 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3868 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003869
3870 create_offload_callback_thread(out);
3871
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003872 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303873 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003874 if (ret != 0) {
3875 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3876 __func__, ret);
3877 goto error_open;
3878 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003879 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3880 if (config->sample_rate == 0)
3881 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3882 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3883 config->sample_rate != 8000) {
3884 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3885 ret = -EINVAL;
3886 goto error_open;
3887 }
3888 out->sample_rate = config->sample_rate;
3889 out->config.rate = config->sample_rate;
3890 if (config->format == AUDIO_FORMAT_DEFAULT)
3891 config->format = AUDIO_FORMAT_PCM_16_BIT;
3892 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3893 config->format = AUDIO_FORMAT_PCM_16_BIT;
3894 ret = -EINVAL;
3895 goto error_open;
3896 }
3897 out->format = config->format;
3898 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3899 out->config = pcm_config_afe_proxy_playback;
3900 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003901 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303902 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3903 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003904 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3905 out->flags);
3906 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303907 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3908 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3909 out->config = pcm_config_low_latency;
3910 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3911 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3912 out->config = pcm_config_deep_buffer;
3913 } else {
3914 /* primary path is the default path selected if no other outputs are available/suitable */
3915 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3916 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3917 }
3918 out->hal_ip_format = format = out->format;
3919 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3920 out->hal_op_format = pcm_format_to_hal(out->config.format);
3921 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3922 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003923 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303924 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3925 if (out->hal_ip_format != out->hal_op_format) {
3926 uint32_t buffer_size = out->config.period_size *
3927 format_to_bitwidth_table[out->hal_op_format] *
3928 out->config.channels;
3929 out->convert_buffer = calloc(1, buffer_size);
3930 if (out->convert_buffer == NULL){
3931 ALOGE("Allocation failed for convert buffer for size %d",
3932 out->compr_config.fragment_size);
3933 ret = -ENOMEM;
3934 goto error_open;
3935 }
3936 ALOGD("Convert buffer allocated of size %d", buffer_size);
3937 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 }
3939
Ashish Jain83a6cc22016-06-28 14:34:17 +05303940 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3941 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3942
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003943 /* TODO remove this hardcoding and check why width is zero*/
3944 if (out->bit_width == 0)
3945 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003946 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3947 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003948 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303949 out->bit_width, out->channel_mask,
3950 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003951 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3952 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3953 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003954 if(adev->primary_output == NULL)
3955 adev->primary_output = out;
3956 else {
3957 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003958 ret = -EEXIST;
3959 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003960 }
3961 }
3962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963 /* Check if this usecase is already existing */
3964 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003965 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3966 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003969 ret = -EEXIST;
3970 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 }
3972 pthread_mutex_unlock(&adev->lock);
3973
3974 out->stream.common.get_sample_rate = out_get_sample_rate;
3975 out->stream.common.set_sample_rate = out_set_sample_rate;
3976 out->stream.common.get_buffer_size = out_get_buffer_size;
3977 out->stream.common.get_channels = out_get_channels;
3978 out->stream.common.get_format = out_get_format;
3979 out->stream.common.set_format = out_set_format;
3980 out->stream.common.standby = out_standby;
3981 out->stream.common.dump = out_dump;
3982 out->stream.common.set_parameters = out_set_parameters;
3983 out->stream.common.get_parameters = out_get_parameters;
3984 out->stream.common.add_audio_effect = out_add_audio_effect;
3985 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3986 out->stream.get_latency = out_get_latency;
3987 out->stream.set_volume = out_set_volume;
3988 out->stream.write = out_write;
3989 out->stream.get_render_position = out_get_render_position;
3990 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003991 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003993 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003995 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003996 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997
3998 config->format = out->stream.common.get_format(&out->stream.common);
3999 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4000 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4001
4002 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304003 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004004 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004005
4006 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4007 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4008 popcount(out->channel_mask), out->playback_started);
4009
Eric Laurent994a6932013-07-17 11:51:42 -07004010 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004012
4013error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304014 if (out->convert_buffer)
4015 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004016 free(out);
4017 *stream_out = NULL;
4018 ALOGD("%s: exit: ret %d", __func__, ret);
4019 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020}
4021
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304022void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023 struct audio_stream_out *stream)
4024{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004025 struct stream_out *out = (struct stream_out *)stream;
4026 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004027 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004028
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304029 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4030
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004031 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304032 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004033 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304034 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004035 if(ret != 0)
4036 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4037 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004038 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004039 out_standby(&stream->common);
4040
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004041 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004042 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004043 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004044 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004045 if (out->compr_config.codec != NULL)
4046 free(out->compr_config.codec);
4047 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004048
Ashish Jain83a6cc22016-06-28 14:34:17 +05304049 if (out->convert_buffer != NULL) {
4050 free(out->convert_buffer);
4051 out->convert_buffer = NULL;
4052 }
4053
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004054 if (adev->voice_tx_output == out)
4055 adev->voice_tx_output = NULL;
4056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004057 pthread_cond_destroy(&out->cond);
4058 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004060 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061}
4062
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004063static void close_compress_sessions(struct audio_device *adev)
4064{
Mingming Yin7b762e72015-03-04 13:47:32 -08004065 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304066 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004067 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004068 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304069
4070 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004071 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304072 if (is_offload_usecase(usecase->id)) {
4073 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004074 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4075 out = usecase->stream.out;
4076 pthread_mutex_unlock(&adev->lock);
4077 out_standby(&out->stream.common);
4078 pthread_mutex_lock(&adev->lock);
4079 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304080 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004081 }
4082 pthread_mutex_unlock(&adev->lock);
4083}
4084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4086{
4087 struct audio_device *adev = (struct audio_device *)dev;
4088 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004090 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004091 int ret;
4092 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004094 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304097 if (!parms)
4098 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004099 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4100 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304101 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304102 if (strstr(snd_card_status, "OFFLINE")) {
4103 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304104 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004105 //close compress sessions on OFFLINE status
4106 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304107 } else if (strstr(snd_card_status, "ONLINE")) {
4108 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304109 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004110 //send dts hpx license if enabled
4111 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304112 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304113 }
4114
4115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004116 status = voice_set_parameters(adev, parms);
4117 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004118 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004120 status = platform_set_parameters(adev->platform, parms);
4121 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004122 goto done;
4123
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004124 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4125 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004126 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4128 adev->bluetooth_nrec = true;
4129 else
4130 adev->bluetooth_nrec = false;
4131 }
4132
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004133 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4134 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4136 adev->screen_off = false;
4137 else
4138 adev->screen_off = true;
4139 }
4140
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004141 ret = str_parms_get_int(parms, "rotation", &val);
4142 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004143 bool reverse_speakers = false;
4144 switch(val) {
4145 // FIXME: note that the code below assumes that the speakers are in the correct placement
4146 // relative to the user when the device is rotated 90deg from its default rotation. This
4147 // assumption is device-specific, not platform-specific like this code.
4148 case 270:
4149 reverse_speakers = true;
4150 break;
4151 case 0:
4152 case 90:
4153 case 180:
4154 break;
4155 default:
4156 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004157 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004158 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004159 if (status == 0) {
4160 if (adev->speaker_lr_swap != reverse_speakers) {
4161 adev->speaker_lr_swap = reverse_speakers;
4162 // only update the selected device if there is active pcm playback
4163 struct audio_usecase *usecase;
4164 struct listnode *node;
4165 list_for_each(node, &adev->usecase_list) {
4166 usecase = node_to_item(node, struct audio_usecase, list);
4167 if (usecase->type == PCM_PLAYBACK) {
4168 select_devices(adev, usecase->id);
4169 break;
4170 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004171 }
4172 }
4173 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004174 }
4175
Mingming Yin514a8bc2014-07-29 15:22:21 -07004176 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4177 if (ret >= 0) {
4178 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4179 adev->bt_wb_speech_enabled = true;
4180 else
4181 adev->bt_wb_speech_enabled = false;
4182 }
4183
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004184 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4185 if (ret >= 0) {
4186 val = atoi(value);
4187 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004188 ALOGV("cache new ext disp type and edid");
4189 ret = platform_get_ext_disp_type(adev->platform);
4190 if (ret < 0) {
4191 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4192 return ret;
4193 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004194 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004195 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004196 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004197 /*
4198 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4199 * Per AudioPolicyManager, USB device is higher priority than WFD.
4200 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4201 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4202 * starting voice call on USB
4203 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004204 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4205 if (ret >= 0) {
4206 audio_extn_usb_add_device(val, atoi(value));
4207 }
vivek mehta344576a2016-04-12 18:56:03 -07004208 ALOGV("detected USB connect .. disable proxy");
4209 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004210 }
4211 }
4212
4213 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4214 if (ret >= 0) {
4215 val = atoi(value);
4216 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4217 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004218 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004219 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004220 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004221 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4222 if (ret >= 0) {
4223 audio_extn_usb_remove_device(val, atoi(value));
4224 }
vivek mehta344576a2016-04-12 18:56:03 -07004225 ALOGV("detected USB disconnect .. enable proxy");
4226 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004227 }
4228 }
4229
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304230 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4231 if (ret >= 0) {
4232 struct audio_usecase *usecase;
4233 struct listnode *node;
4234 list_for_each(node, &adev->usecase_list) {
4235 usecase = node_to_item(node, struct audio_usecase, list);
4236 if ((usecase->type == PCM_PLAYBACK) &&
4237 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4238 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304239 lock_output_stream(usecase->stream.out);
4240 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304241 //force device switch to re configure encoder
4242 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304243 audio_extn_a2dp_set_handoff_mode(false);
4244 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304245 break;
4246 }
4247 }
4248 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304249 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004250done:
4251 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004252 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304253error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004254 ALOGV("%s: exit with code(%d)", __func__, status);
4255 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256}
4257
4258static char* adev_get_parameters(const struct audio_hw_device *dev,
4259 const char *keys)
4260{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004261 struct audio_device *adev = (struct audio_device *)dev;
4262 struct str_parms *reply = str_parms_create();
4263 struct str_parms *query = str_parms_create_str(keys);
4264 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304265 char value[256] = {0};
4266 int ret = 0;
4267
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004268 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004269 if (reply) {
4270 str_parms_destroy(reply);
4271 }
4272 if (query) {
4273 str_parms_destroy(query);
4274 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004275 ALOGE("adev_get_parameters: failed to create query or reply");
4276 return NULL;
4277 }
4278
Naresh Tannirud7205b62014-06-20 02:54:48 +05304279 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4280 sizeof(value));
4281 if (ret >=0) {
4282 int val = 1;
4283 pthread_mutex_lock(&adev->snd_card_status.lock);
4284 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4285 val = 0;
4286 pthread_mutex_unlock(&adev->snd_card_status.lock);
4287 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4288 goto exit;
4289 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004290
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004291 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004292 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004293 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004294 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304295 pthread_mutex_unlock(&adev->lock);
4296
Naresh Tannirud7205b62014-06-20 02:54:48 +05304297exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004298 str = str_parms_to_str(reply);
4299 str_parms_destroy(query);
4300 str_parms_destroy(reply);
4301
4302 ALOGV("%s: exit: returns - %s", __func__, str);
4303 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304}
4305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004306static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307{
4308 return 0;
4309}
4310
4311static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4312{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004313 int ret;
4314 struct audio_device *adev = (struct audio_device *)dev;
4315 pthread_mutex_lock(&adev->lock);
4316 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004317 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004318 pthread_mutex_unlock(&adev->lock);
4319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320}
4321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004322static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4323 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324{
4325 return -ENOSYS;
4326}
4327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004328static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4329 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330{
4331 return -ENOSYS;
4332}
4333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004334static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4335 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336{
4337 return -ENOSYS;
4338}
4339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004340static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4341 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342{
4343 return -ENOSYS;
4344}
4345
4346static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4347{
4348 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350 pthread_mutex_lock(&adev->lock);
4351 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004352 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004354 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004355 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004356 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004357 adev->current_call_output = NULL;
4358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 }
4360 pthread_mutex_unlock(&adev->lock);
4361 return 0;
4362}
4363
4364static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4365{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004366 int ret;
4367
4368 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004369 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004370 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4371 pthread_mutex_unlock(&adev->lock);
4372
4373 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374}
4375
4376static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4377{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004378 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 return 0;
4380}
4381
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004382static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 const struct audio_config *config)
4384{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004385 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004387 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4388 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389}
4390
4391static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004392 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 audio_devices_t devices,
4394 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004395 struct audio_stream_in **stream_in,
4396 audio_input_flags_t flags __unused,
4397 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004398 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399{
4400 struct audio_device *adev = (struct audio_device *)dev;
4401 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004402 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004403 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004404 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304407 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4408 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304410 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411
4412 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004413
4414 if (!in) {
4415 ALOGE("failed to allocate input stream");
4416 return -ENOMEM;
4417 }
4418
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304419 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304420 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4421 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004422 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004423 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425 in->stream.common.get_sample_rate = in_get_sample_rate;
4426 in->stream.common.set_sample_rate = in_set_sample_rate;
4427 in->stream.common.get_buffer_size = in_get_buffer_size;
4428 in->stream.common.get_channels = in_get_channels;
4429 in->stream.common.get_format = in_get_format;
4430 in->stream.common.set_format = in_set_format;
4431 in->stream.common.standby = in_standby;
4432 in->stream.common.dump = in_dump;
4433 in->stream.common.set_parameters = in_set_parameters;
4434 in->stream.common.get_parameters = in_get_parameters;
4435 in->stream.common.add_audio_effect = in_add_audio_effect;
4436 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4437 in->stream.set_gain = in_set_gain;
4438 in->stream.read = in_read;
4439 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4440
4441 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004442 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 in->standby = 1;
4445 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004446 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004447 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448
4449 /* Update config params with the requested sample rate and channels */
4450 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004451 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4452 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4453 is_low_latency = true;
4454#if LOW_LATENCY_CAPTURE_USE_CASE
4455 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4456#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004457 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004458 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004459
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004460 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004461 if (in->realtime) {
4462 in->config = pcm_config_audio_capture_rt;
4463 in->sample_rate = in->config.rate;
4464 in->af_period_multiplier = af_period_multiplier;
4465 } else {
4466 in->config = pcm_config_audio_capture;
4467 in->config.rate = config->sample_rate;
4468 in->sample_rate = config->sample_rate;
4469 in->af_period_multiplier = 1;
4470 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304471 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004473 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304474 if (adev->mode != AUDIO_MODE_IN_CALL) {
4475 ret = -EINVAL;
4476 goto err_open;
4477 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004478 if (config->sample_rate == 0)
4479 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4480 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4481 config->sample_rate != 8000) {
4482 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4483 ret = -EINVAL;
4484 goto err_open;
4485 }
4486 if (config->format == AUDIO_FORMAT_DEFAULT)
4487 config->format = AUDIO_FORMAT_PCM_16_BIT;
4488 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4489 config->format = AUDIO_FORMAT_PCM_16_BIT;
4490 ret = -EINVAL;
4491 goto err_open;
4492 }
4493
4494 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4495 in->config = pcm_config_afe_proxy_record;
4496 in->config.channels = channel_count;
4497 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304498 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304499 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4500 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004501 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004502 audio_extn_compr_cap_format_supported(config->format) &&
4503 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004504 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004505 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304506 /* restrict 24 bit capture for unprocessed source only
4507 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4508 */
4509 if (config->format == AUDIO_FORMAT_DEFAULT) {
4510 config->format = AUDIO_FORMAT_PCM_16_BIT;
4511 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4512 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4513 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4514 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4515 bool ret_error = false;
4516 in->bit_width = 24;
4517 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4518 from HAL is 24_packed and 8_24
4519 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4520 24_packed return error indicating supported format is 24_packed
4521 *> In case of any other source requesting 24 bit or float return error
4522 indicating format supported is 16 bit only.
4523
4524 on error flinger will retry with supported format passed
4525 */
4526 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4527 (source != AUDIO_SOURCE_CAMCORDER)) {
4528 config->format = AUDIO_FORMAT_PCM_16_BIT;
4529 if( config->sample_rate > 48000)
4530 config->sample_rate = 48000;
4531 ret_error = true;
4532 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4533 in->config.format = PCM_FORMAT_S24_3LE;
4534 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4535 in->config.format = PCM_FORMAT_S24_LE;
4536 } else {
4537 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4538 ret_error = true;
4539 }
4540
4541 if (ret_error) {
4542 ret = -EINVAL;
4543 goto err_open;
4544 }
4545 }
4546
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004547 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004548 if (!in->realtime) {
4549 in->format = config->format;
4550 frame_size = audio_stream_in_frame_size(&in->stream);
4551 buffer_size = get_input_buffer_size(config->sample_rate,
4552 config->format,
4553 channel_count,
4554 is_low_latency);
4555 in->config.period_size = buffer_size / frame_size;
4556 }
4557
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004558 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4559 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4560 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004561 (in->config.rate == 8000 || in->config.rate == 16000 ||
4562 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004563 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4564 voice_extn_compress_voip_open_input_stream(in);
4565 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004566 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004568 /* This stream could be for sound trigger lab,
4569 get sound trigger pcm if present */
4570 audio_extn_sound_trigger_check_and_get_session(in);
4571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004573 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004574 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575
4576err_open:
4577 free(in);
4578 *stream_in = NULL;
4579 return ret;
4580}
4581
4582static void adev_close_input_stream(struct audio_hw_device *dev,
4583 struct audio_stream_in *stream)
4584{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004585 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004586 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004587 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304588
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304589 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004590
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304591 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004592 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304593
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004594 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304595 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004596 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304597 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004598 if (ret != 0)
4599 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4600 __func__, ret);
4601 } else
4602 in_standby(&stream->common);
4603
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004604 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004605 audio_extn_ssr_deinit();
4606 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607
Mingming Yine62d7842013-10-25 16:26:03 -07004608 if(audio_extn_compr_cap_enabled() &&
4609 audio_extn_compr_cap_format_supported(in->config.format))
4610 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004611
Mingming Yinfd7607b2016-01-22 12:48:44 -08004612 if (in->is_st_session) {
4613 ALOGV("%s: sound trigger pcm stop lab", __func__);
4614 audio_extn_sound_trigger_stop_lab(in);
4615 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004616 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 return;
4618}
4619
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004620static int adev_dump(const audio_hw_device_t *device __unused,
4621 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622{
4623 return 0;
4624}
4625
4626static int adev_close(hw_device_t *device)
4627{
4628 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004629
4630 if (!adev)
4631 return 0;
4632
4633 pthread_mutex_lock(&adev_init_lock);
4634
4635 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004636 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004637 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304638 if (audio_extn_qaf_is_enabled())
4639 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004640 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004641 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004642 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004643 free(adev->snd_dev_ref_cnt);
4644 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004645 if (adev->adm_deinit)
4646 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004647 free(device);
4648 adev = NULL;
4649 }
4650 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 return 0;
4653}
4654
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004655/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4656 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4657 * just that it _might_ work.
4658 */
4659static int period_size_is_plausible_for_low_latency(int period_size)
4660{
4661 switch (period_size) {
4662 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004663 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004664 case 240:
4665 case 320:
4666 case 480:
4667 return 1;
4668 default:
4669 return 0;
4670 }
4671}
4672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673static int adev_open(const hw_module_t *module, const char *name,
4674 hw_device_t **device)
4675{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304676 int ret;
4677
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004678 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4680
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004681 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004682 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004683 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004684 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004685 ALOGD("%s: returning existing instance of adev", __func__);
4686 ALOGD("%s: exit", __func__);
4687 pthread_mutex_unlock(&adev_init_lock);
4688 return 0;
4689 }
4690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 adev = calloc(1, sizeof(struct audio_device));
4692
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004693 if (!adev) {
4694 pthread_mutex_unlock(&adev_init_lock);
4695 return -ENOMEM;
4696 }
4697
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004698 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4701 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4702 adev->device.common.module = (struct hw_module_t *)module;
4703 adev->device.common.close = adev_close;
4704
4705 adev->device.init_check = adev_init_check;
4706 adev->device.set_voice_volume = adev_set_voice_volume;
4707 adev->device.set_master_volume = adev_set_master_volume;
4708 adev->device.get_master_volume = adev_get_master_volume;
4709 adev->device.set_master_mute = adev_set_master_mute;
4710 adev->device.get_master_mute = adev_get_master_mute;
4711 adev->device.set_mode = adev_set_mode;
4712 adev->device.set_mic_mute = adev_set_mic_mute;
4713 adev->device.get_mic_mute = adev_get_mic_mute;
4714 adev->device.set_parameters = adev_set_parameters;
4715 adev->device.get_parameters = adev_get_parameters;
4716 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4717 adev->device.open_output_stream = adev_open_output_stream;
4718 adev->device.close_output_stream = adev_close_output_stream;
4719 adev->device.open_input_stream = adev_open_input_stream;
4720 adev->device.close_input_stream = adev_close_input_stream;
4721 adev->device.dump = adev_dump;
4722
4723 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004725 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004726 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004729 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004730 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004731 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004732 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004733 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004734 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004735 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004736 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304737 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304738 adev->perf_lock_opts[0] = 0x101;
4739 adev->perf_lock_opts[1] = 0x20E;
4740 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304741
4742 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4743 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004745 adev->platform = platform_init(adev);
4746 if (!adev->platform) {
4747 free(adev->snd_dev_ref_cnt);
4748 free(adev);
4749 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4750 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004751 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304752 pthread_mutex_destroy(&adev->lock);
4753 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004754 return -EINVAL;
4755 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004756
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304757 if (audio_extn_qaf_is_enabled()) {
4758 ret = audio_extn_qaf_init(adev);
4759 if (ret < 0) {
4760 free(adev);
4761 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4762 *device = NULL;
4763 pthread_mutex_unlock(&adev_init_lock);
4764 pthread_mutex_destroy(&adev->lock);
4765 return ret;
4766 }
4767
4768 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4769 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4770 }
4771
Naresh Tanniru4c630392014-05-12 01:05:52 +05304772 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4773
Eric Laurentc4aef752013-09-12 17:45:53 -07004774 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4775 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4776 if (adev->visualizer_lib == NULL) {
4777 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4778 } else {
4779 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4780 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004781 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004782 "visualizer_hal_start_output");
4783 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004784 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004785 "visualizer_hal_stop_output");
4786 }
4787 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004788 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004789 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004790 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004791
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004792 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4793 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4794 if (adev->offload_effects_lib == NULL) {
4795 ALOGE("%s: DLOPEN failed for %s", __func__,
4796 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4797 } else {
4798 ALOGV("%s: DLOPEN successful for %s", __func__,
4799 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4800 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304801 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004802 "offload_effects_bundle_hal_start_output");
4803 adev->offload_effects_stop_output =
4804 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4805 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004806 adev->offload_effects_set_hpx_state =
4807 (int (*)(bool))dlsym(adev->offload_effects_lib,
4808 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304809 adev->offload_effects_get_parameters =
4810 (void (*)(struct str_parms *, struct str_parms *))
4811 dlsym(adev->offload_effects_lib,
4812 "offload_effects_bundle_get_parameters");
4813 adev->offload_effects_set_parameters =
4814 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4815 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004816 }
4817 }
4818
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004819 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4820 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4821 if (adev->adm_lib == NULL) {
4822 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4823 } else {
4824 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4825 adev->adm_init = (adm_init_t)
4826 dlsym(adev->adm_lib, "adm_init");
4827 adev->adm_deinit = (adm_deinit_t)
4828 dlsym(adev->adm_lib, "adm_deinit");
4829 adev->adm_register_input_stream = (adm_register_input_stream_t)
4830 dlsym(adev->adm_lib, "adm_register_input_stream");
4831 adev->adm_register_output_stream = (adm_register_output_stream_t)
4832 dlsym(adev->adm_lib, "adm_register_output_stream");
4833 adev->adm_deregister_stream = (adm_deregister_stream_t)
4834 dlsym(adev->adm_lib, "adm_deregister_stream");
4835 adev->adm_request_focus = (adm_request_focus_t)
4836 dlsym(adev->adm_lib, "adm_request_focus");
4837 adev->adm_abandon_focus = (adm_abandon_focus_t)
4838 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004839 adev->adm_set_config = (adm_set_config_t)
4840 dlsym(adev->adm_lib, "adm_set_config");
4841 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4842 dlsym(adev->adm_lib, "adm_request_focus_v2");
4843 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4844 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4845 adev->adm_on_routing_change = (adm_on_routing_change_t)
4846 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004847 }
4848 }
4849
Mingming Yin514a8bc2014-07-29 15:22:21 -07004850 adev->bt_wb_speech_enabled = false;
4851
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004852 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 *device = &adev->device.common;
4854
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004855 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4856 &adev->streams_output_cfg_list);
4857
Kiran Kandi910e1862013-10-29 13:29:42 -07004858 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004859
4860 char value[PROPERTY_VALUE_MAX];
4861 int trial;
4862 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4863 trial = atoi(value);
4864 if (period_size_is_plausible_for_low_latency(trial)) {
4865 pcm_config_low_latency.period_size = trial;
4866 pcm_config_low_latency.start_threshold = trial / 4;
4867 pcm_config_low_latency.avail_min = trial / 4;
4868 configured_low_latency_capture_period_size = trial;
4869 }
4870 }
4871 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4872 trial = atoi(value);
4873 if (period_size_is_plausible_for_low_latency(trial)) {
4874 configured_low_latency_capture_period_size = trial;
4875 }
4876 }
4877
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004878 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4879 af_period_multiplier = atoi(value);
4880 if (af_period_multiplier < 0)
4881 af_period_multiplier = 2;
4882 else if (af_period_multiplier > 4)
4883 af_period_multiplier = 4;
4884
4885 ALOGV("new period_multiplier = %d", af_period_multiplier);
4886 }
4887
vivek mehta446c3962015-09-14 10:57:35 -07004888 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004889 pthread_mutex_unlock(&adev_init_lock);
4890
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004891 if (adev->adm_init)
4892 adev->adm_data = adev->adm_init();
4893
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304894 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004895 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896 return 0;
4897}
4898
4899static struct hw_module_methods_t hal_module_methods = {
4900 .open = adev_open,
4901};
4902
4903struct audio_module HAL_MODULE_INFO_SYM = {
4904 .common = {
4905 .tag = HARDWARE_MODULE_TAG,
4906 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4907 .hal_api_version = HARDWARE_HAL_API_VERSION,
4908 .id = AUDIO_HARDWARE_MODULE_ID,
4909 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004910 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 .methods = &hal_module_methods,
4912 },
4913};