blob: 13e4ae9e5e89b55d413ce494cbbbfd59c0c71c3a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530799 } else if (platform_can_split_snd_device(adev->platform, snd_device,
800 &num_devices, new_snd_devices)) {
801 for (i = 0; i < num_devices; i++) {
802 enable_snd_device(adev, new_snd_devices[i]);
803 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700805 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530806
807 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
808 (audio_extn_a2dp_start_playback() < 0)) {
809 ALOGE(" fail to configure A2dp control path ");
810 return -EINVAL;
811 }
812
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700813 /* due to the possibility of calibration overwrite between listen
814 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700815 audio_extn_sound_trigger_update_device_status(snd_device,
816 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530817 audio_extn_listen_update_device_status(snd_device,
818 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700819 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700820 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700821 audio_extn_sound_trigger_update_device_status(snd_device,
822 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530823 audio_extn_listen_update_device_status(snd_device,
824 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700825 return -EINVAL;
826 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300827 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700828 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530829
830 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
831 !adev->native_playback_enabled &&
832 audio_is_true_native_stream_active(adev)) {
833 ALOGD("%s: %d: napb: enabling native mode in hardware",
834 __func__, __LINE__);
835 audio_route_apply_and_update_path(adev->audio_route,
836 "true-native-mode");
837 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840 return 0;
841}
842
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700843int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700844 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530846 int i, num_devices = 0;
847 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700848 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
849
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 if (snd_device < SND_DEVICE_MIN ||
851 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800853 return -EINVAL;
854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
856 ALOGE("%s: device ref cnt is already 0", __func__);
857 return -EINVAL;
858 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700861
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
863 ALOGE("%s: Invalid sound device returned", __func__);
864 return -EINVAL;
865 }
866
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700868 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530869
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800870 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
871 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700872 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 } else if (platform_can_split_snd_device(adev->platform, snd_device,
874 &num_devices, new_snd_devices)) {
875 for (i = 0; i < num_devices; i++) {
876 disable_snd_device(adev, new_snd_devices[i]);
877 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300878 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700879 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300880 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700881
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530882 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
883 audio_extn_a2dp_stop_playback();
884
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700885 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530886 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530887 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
888 adev->native_playback_enabled) {
889 ALOGD("%s: %d: napb: disabling native mode in hardware",
890 __func__, __LINE__);
891 audio_route_reset_and_update_path(adev->audio_route,
892 "true-native-mode");
893 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530894 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
895 adev->asrc_mode_enabled) {
896 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530897 disable_asrc_mode(adev);
898 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530899 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200901 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700902 audio_extn_sound_trigger_update_device_status(snd_device,
903 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530904 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800905 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 return 0;
909}
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530919 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /*
921 * This function is to make sure that all the usecases that are active on
922 * the hardware codec backend are always routed to any one device that is
923 * handled by the hardware codec.
924 * For example, if low-latency and deep-buffer usecases are currently active
925 * on speaker and out_set_parameters(headset) is received on low-latency
926 * output, then we have to make sure deep-buffer is also switched to headset,
927 * because of the limitation that both the devices cannot be enabled
928 * at the same time as they share the same backend.
929 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700930 /*
931 * This call is to check if we need to force routing for a particular stream
932 * If there is a backend configuration change for the device when a
933 * new stream starts, then ADM needs to be closed and re-opened with the new
934 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800935 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700936 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800937 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
938 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530939 /* For a2dp device reconfigure all active sessions
940 * with new AFE encoder format based on a2dp state
941 */
942 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
943 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
944 audio_extn_a2dp_is_force_device_switch()) {
945 force_routing = true;
946 force_restart_session = true;
947 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530948 ALOGD("%s:becf: force routing %d", __func__, force_routing);
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800952 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
954 switch_device[i] = false;
955
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800958
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530959 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
960 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530962 platform_get_snd_device_name(usecase->out_snd_device),
963 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800964 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530965 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530966 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530967 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
968 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530969 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530970 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530971 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
972
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530973 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
974 __func__, use_case_table[usecase->id],
975 platform_get_snd_device_name(usecase->out_snd_device));
976 disable_audio_route(adev, usecase);
977 switch_device[usecase->id] = true;
978 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980 }
981
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
983 num_uc_to_switch);
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700986 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530988 /* Make sure the previous devices to be disabled first and then enable the
989 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 list_for_each(node, &adev->usecase_list) {
991 usecase = node_to_item(node, struct audio_usecase, list);
992 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700993 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 }
995 }
996
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700997 list_for_each(node, &adev->usecase_list) {
998 usecase = node_to_item(node, struct audio_usecase, list);
999 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001000 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 /* Re-route all the usecases on the shared backend other than the
1005 specified usecase to new snd devices */
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301008 /* Update the out_snd_device only before enabling the audio route */
1009 if (switch_device[usecase->id]) {
1010 usecase->out_snd_device = snd_device;
1011 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301012 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301013 use_case_table[usecase->id],
1014 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301015 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 }
1018 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 }
1020}
1021
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301022static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001023 struct audio_usecase *uc_info,
1024 snd_device_t snd_device)
1025{
1026 struct listnode *node;
1027 struct audio_usecase *usecase;
1028 bool switch_device[AUDIO_USECASE_MAX];
1029 int i, num_uc_to_switch = 0;
1030
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301031 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1032 snd_device);
1033 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034 /*
1035 * This function is to make sure that all the active capture usecases
1036 * are always routed to the same input sound device.
1037 * For example, if audio-record and voice-call usecases are currently
1038 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1039 * is received for voice call then we have to make sure that audio-record
1040 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1041 * because of the limitation that two devices cannot be enabled
1042 * at the same time if they share the same backend.
1043 */
1044 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1045 switch_device[i] = false;
1046
1047 list_for_each(node, &adev->usecase_list) {
1048 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001049 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301051 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001052 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301053 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001054 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001055 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001058 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
1062 }
1063 }
1064
1065 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001066 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001067
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301068 /* Make sure the previous devices to be disabled first and then enable the
1069 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001070 list_for_each(node, &adev->usecase_list) {
1071 usecase = node_to_item(node, struct audio_usecase, list);
1072 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001073 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001074 }
1075 }
1076
1077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 }
1082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 /* Re-route all the usecases on the shared backend other than the
1085 specified usecase to new snd devices */
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 /* Update the in_snd_device only before enabling the audio route */
1089 if (switch_device[usecase->id] ) {
1090 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001091 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301092 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001093 }
1094 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001095 }
1096}
1097
Mingming Yin3a941d42016-02-17 18:08:05 -08001098static void reset_hdmi_sink_caps(struct stream_out *out) {
1099 int i = 0;
1100
1101 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1102 out->supported_channel_masks[i] = 0;
1103 }
1104 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1105 out->supported_formats[i] = 0;
1106 }
1107 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1108 out->supported_sample_rates[i] = 0;
1109 }
1110}
1111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001113static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114{
Mingming Yin3a941d42016-02-17 18:08:05 -08001115 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001116 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Mingming Yin3a941d42016-02-17 18:08:05 -08001118 reset_hdmi_sink_caps(out);
1119
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001120 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001121 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001122 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001123 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001124 }
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001129 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001130 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1131 case 6:
1132 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1133 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1134 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1135 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1136 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1137 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 break;
1139 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001140 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001141 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 break;
1143 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001144
1145 // check channel format caps
1146 i = 0;
1147 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1148 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1149 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1150 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1151 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1152 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1153 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1154 }
1155
1156 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1157 ALOGV(":%s HDMI supports DTS format", __func__);
1158 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1159 }
1160
1161 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1162 ALOGV(":%s HDMI supports DTS HD format", __func__);
1163 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1164 }
1165
1166
1167 // check sample rate caps
1168 i = 0;
1169 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1170 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1171 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1172 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1173 }
1174 }
1175
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001176 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177}
1178
Alexy Josephb1379942016-01-29 15:49:38 -08001179audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001180 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001181{
1182 struct audio_usecase *usecase;
1183 struct listnode *node;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001187 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001188 ALOGV("%s: usecase id %d", __func__, usecase->id);
1189 return usecase->id;
1190 }
1191 }
1192 return USECASE_INVALID;
1193}
1194
Alexy Josephb1379942016-01-29 15:49:38 -08001195struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001196 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197{
1198 struct audio_usecase *usecase;
1199 struct listnode *node;
1200
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (usecase->id == uc_id)
1204 return usecase;
1205 }
1206 return NULL;
1207}
1208
Dhananjay Kumard4833242016-10-06 22:09:12 +05301209struct stream_in *get_next_active_input(const struct audio_device *adev)
1210{
1211 struct audio_usecase *usecase;
1212 struct listnode *node;
1213
1214 list_for_each_reverse(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (usecase->type == PCM_CAPTURE)
1217 return usecase->stream.in;
1218 }
1219 return NULL;
1220}
1221
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301222/*
1223 * is a true native playback active
1224 */
1225bool audio_is_true_native_stream_active(struct audio_device *adev)
1226{
1227 bool active = false;
1228 int i = 0;
1229 struct listnode *node;
1230
1231 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1232 ALOGV("%s:napb: not in true mode or non hdphones device",
1233 __func__);
1234 active = false;
1235 goto exit;
1236 }
1237
1238 list_for_each(node, &adev->usecase_list) {
1239 struct audio_usecase *uc;
1240 uc = node_to_item(node, struct audio_usecase, list);
1241 struct stream_out *curr_out =
1242 (struct stream_out*) uc->stream.out;
1243
1244 if (curr_out && PCM_PLAYBACK == uc->type) {
1245 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1246 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1247 uc->id, curr_out->sample_rate,
1248 curr_out->bit_width,
1249 platform_get_snd_device_name(uc->out_snd_device));
1250
1251 if (is_offload_usecase(uc->id) &&
1252 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1253 active = true;
1254 ALOGD("%s:napb:native stream detected", __func__);
1255 }
1256 }
1257 }
1258exit:
1259 return active;
1260}
1261
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301262/*
1263 * if native DSD playback active
1264 */
1265bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1266{
1267 bool active = false;
1268 struct listnode *node = NULL;
1269 struct audio_usecase *uc = NULL;
1270 struct stream_out *curr_out = NULL;
1271
1272 list_for_each(node, &adev->usecase_list) {
1273 uc = node_to_item(node, struct audio_usecase, list);
1274 curr_out = (struct stream_out*) uc->stream.out;
1275
1276 if (curr_out && PCM_PLAYBACK == uc->type &&
1277 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1278 active = true;
1279 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301280 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301281 }
1282 }
1283 return active;
1284}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301285
1286static bool force_device_switch(struct audio_usecase *usecase)
1287{
1288 bool ret = false;
1289 bool is_it_true_mode = false;
1290
1291 if (is_offload_usecase(usecase->id) &&
1292 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001293 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1294 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1295 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301296 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1297 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1298 (!is_it_true_mode && adev->native_playback_enabled)){
1299 ret = true;
1300 ALOGD("napb: time to toggle native mode");
1301 }
1302 }
1303
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301304 // Force all a2dp output devices to reconfigure for proper AFE encode format
1305 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001306 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301307 audio_extn_a2dp_is_force_device_switch()) {
1308 ALOGD("Force a2dp device switch to update new encoder config");
1309 ret = true;
1310 }
1311
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301312 return ret;
1313}
1314
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001315int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001317 snd_device_t out_snd_device = SND_DEVICE_NONE;
1318 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 struct audio_usecase *usecase = NULL;
1320 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001321 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001322 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001323 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301326 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1327
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328 usecase = get_usecase_from_list(adev, uc_id);
1329 if (usecase == NULL) {
1330 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1331 return -EINVAL;
1332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001334 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001335 (usecase->type == VOIP_CALL) ||
1336 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301337 if(usecase->stream.out == NULL) {
1338 ALOGE("%s: stream.out is NULL", __func__);
1339 return -EINVAL;
1340 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001341 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001342 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001343 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001344 usecase->devices = usecase->stream.out->devices;
1345 } else {
1346 /*
1347 * If the voice call is active, use the sound devices of voice call usecase
1348 * so that it would not result any device switch. All the usecases will
1349 * be switched to new device when select_devices() is called for voice call
1350 * usecase. This is to avoid switching devices for voice call when
1351 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001352 * choose voice call device only if the use case device is
1353 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001355 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001356 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001357 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001358 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1359 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301360 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1361 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001362 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001363 in_snd_device = vc_usecase->in_snd_device;
1364 out_snd_device = vc_usecase->out_snd_device;
1365 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001366 } else if (voice_extn_compress_voip_is_active(adev)) {
1367 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001368 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001369 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1370 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001371 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001372 in_snd_device = voip_usecase->in_snd_device;
1373 out_snd_device = voip_usecase->out_snd_device;
1374 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001375 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001376 hfp_ucid = audio_extn_hfp_get_usecase();
1377 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001378 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001379 in_snd_device = hfp_usecase->in_snd_device;
1380 out_snd_device = hfp_usecase->out_snd_device;
1381 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001382 }
1383 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301384 if (usecase->stream.out == NULL) {
1385 ALOGE("%s: stream.out is NULL", __func__);
1386 return -EINVAL;
1387 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 usecase->devices = usecase->stream.out->devices;
1389 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001390 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001391 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001392 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001393 if (usecase->stream.out == adev->primary_output &&
1394 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001395 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001396 select_devices(adev, adev->active_input->usecase);
1397 }
1398 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001399 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301400 if (usecase->stream.in == NULL) {
1401 ALOGE("%s: stream.in is NULL", __func__);
1402 return -EINVAL;
1403 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404 usecase->devices = usecase->stream.in->device;
1405 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001406 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001407 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001408 if (adev->active_input &&
1409 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301410 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1411 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1412 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001413 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001414 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001415 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1416 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001417 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001418 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001419 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420 }
1421 }
1422
1423 if (out_snd_device == usecase->out_snd_device &&
1424 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301425
1426 if (!force_device_switch(usecase))
1427 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 }
1429
sangwoobc677242013-08-08 16:53:43 +09001430 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001431 out_snd_device, platform_get_snd_device_name(out_snd_device),
1432 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 /*
1435 * Limitation: While in call, to do a device switch we need to disable
1436 * and enable both RX and TX devices though one of them is same as current
1437 * device.
1438 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001439 if ((usecase->type == VOICE_CALL) &&
1440 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1441 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001442 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001443 }
1444
1445 if (((usecase->type == VOICE_CALL) ||
1446 (usecase->type == VOIP_CALL)) &&
1447 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1448 /* Disable sidetone only if voice/voip call already exists */
1449 if (voice_is_call_state_active(adev) ||
1450 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001451 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001452
1453 /* Disable aanc only if voice call exists */
1454 if (voice_is_call_state_active(adev))
1455 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001456 }
1457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 /* Disable current sound devices */
1459 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001460 disable_audio_route(adev, usecase);
1461 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462 }
1463
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001465 disable_audio_route(adev, usecase);
1466 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 }
1468
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001469 /* Applicable only on the targets that has external modem.
1470 * New device information should be sent to modem before enabling
1471 * the devices to reduce in-call device switch time.
1472 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001473 if ((usecase->type == VOICE_CALL) &&
1474 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1475 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001476 status = platform_switch_voice_call_enable_device_config(adev->platform,
1477 out_snd_device,
1478 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001479 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001480
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 /* Enable new sound devices */
1482 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001483 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301484 if (platform_check_codec_asrc_support(adev->platform))
1485 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001486 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 }
1488
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001489 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301490 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001492 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493
Avinash Vaish71a8b972014-07-24 15:36:33 +05301494 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001495 status = platform_switch_voice_call_device_post(adev->platform,
1496 out_snd_device,
1497 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301498 enable_audio_route_for_voice_usecases(adev, usecase);
1499 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001500
sangwoo170731f2013-06-08 15:36:36 +09001501 usecase->in_snd_device = in_snd_device;
1502 usecase->out_snd_device = out_snd_device;
1503
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301504 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001505 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301506 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001507 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301508 usecase->stream.out->flags,
1509 usecase->stream.out->format,
1510 usecase->stream.out->sample_rate,
1511 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301512 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301513 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001514 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001515
1516 /* Notify device change info to effect clients registered */
1517 audio_extn_gef_notify_device_config(
1518 usecase->stream.out->devices,
1519 usecase->stream.out->channel_mask,
1520 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301521 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001522
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001523 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001524
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001525 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001526 /* Enable aanc only if voice call exists */
1527 if (voice_is_call_state_active(adev))
1528 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1529
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001530 /* Enable sidetone only if other voice/voip call already exists */
1531 if (voice_is_call_state_active(adev) ||
1532 voice_extn_compress_voip_is_started(adev))
1533 voice_set_sidetone(adev, out_snd_device, true);
1534 }
1535
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001536 /* Applicable only on the targets that has external modem.
1537 * Enable device command should be sent to modem only after
1538 * enabling voice call mixer controls
1539 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001540 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001541 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1542 out_snd_device,
1543 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301544 ALOGD("%s: done",__func__);
1545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 return status;
1547}
1548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549static int stop_input_stream(struct stream_in *in)
1550{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301551 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 struct audio_usecase *uc_info;
1553 struct audio_device *adev = in->dev;
1554
Dhananjay Kumard4833242016-10-06 22:09:12 +05301555 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Eric Laurent994a6932013-07-17 11:51:42 -07001557 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 uc_info = get_usecase_from_list(adev, in->usecase);
1560 if (uc_info == NULL) {
1561 ALOGE("%s: Could not find the usecase (%d) in the list",
1562 __func__, in->usecase);
1563 return -EINVAL;
1564 }
1565
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001566 /* Close in-call recording streams */
1567 voice_check_and_stop_incall_rec_usecase(adev, in);
1568
Eric Laurent150dbfe2013-02-27 14:31:02 -08001569 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001570 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571
1572 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001573 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001575 list_remove(&uc_info->list);
1576 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577
Eric Laurent994a6932013-07-17 11:51:42 -07001578 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 return ret;
1580}
1581
1582int start_input_stream(struct stream_in *in)
1583{
1584 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001585 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 struct audio_usecase *uc_info;
1587 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301588 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589
Mingming Yin2664a5b2015-09-03 10:53:11 -07001590 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1591 if (get_usecase_from_list(adev, usecase) == NULL)
1592 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301593 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1594 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001595
Naresh Tanniru80659832014-06-04 18:17:56 +05301596
1597 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301598 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301599 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301600 goto error_config;
1601 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301602
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001603 /* Check if source matches incall recording usecase criteria */
1604 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1605 if (ret)
1606 goto error_config;
1607 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001608 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1609
1610 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1611 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1612 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001613 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001614 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001615
Eric Laurentb23d5282013-05-14 15:27:20 -07001616 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 if (in->pcm_device_id < 0) {
1618 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1619 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001620 ret = -EINVAL;
1621 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001623
1624 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001626
1627 if (!uc_info) {
1628 ret = -ENOMEM;
1629 goto error_config;
1630 }
1631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 uc_info->id = in->usecase;
1633 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001634 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635 uc_info->devices = in->device;
1636 uc_info->in_snd_device = SND_DEVICE_NONE;
1637 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001639 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301640 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1641 adev->perf_lock_opts,
1642 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301645 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1646 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001647
1648 unsigned int flags = PCM_IN;
1649 unsigned int pcm_open_retry_count = 0;
1650
1651 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1652 flags |= PCM_MMAP | PCM_NOIRQ;
1653 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001654 } else if (in->realtime) {
1655 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001656 }
1657
1658 while (1) {
1659 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1660 flags, &in->config);
1661 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1662 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1663 if (in->pcm != NULL) {
1664 pcm_close(in->pcm);
1665 in->pcm = NULL;
1666 }
1667 if (pcm_open_retry_count-- == 0) {
1668 ret = -EIO;
1669 goto error_open;
1670 }
1671 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1672 continue;
1673 }
1674 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001676
1677 ALOGV("%s: pcm_prepare", __func__);
1678 ret = pcm_prepare(in->pcm);
1679 if (ret < 0) {
1680 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1681 pcm_close(in->pcm);
1682 in->pcm = NULL;
1683 goto error_open;
1684 }
1685
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001686 register_in_stream(in);
1687 if (in->realtime) {
1688 ret = pcm_start(in->pcm);
1689 if (ret < 0)
1690 goto error_open;
1691 }
1692
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301693 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001694 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001695
Eric Laurentc8400632013-02-14 19:04:54 -08001696 return ret;
1697
1698error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301699 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001701error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301702 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301703 /*
1704 * sleep 50ms to allow sufficient time for kernel
1705 * drivers to recover incases like SSR.
1706 */
1707 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001709
1710 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711}
1712
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001713void lock_input_stream(struct stream_in *in)
1714{
1715 pthread_mutex_lock(&in->pre_lock);
1716 pthread_mutex_lock(&in->lock);
1717 pthread_mutex_unlock(&in->pre_lock);
1718}
1719
1720void lock_output_stream(struct stream_out *out)
1721{
1722 pthread_mutex_lock(&out->pre_lock);
1723 pthread_mutex_lock(&out->lock);
1724 pthread_mutex_unlock(&out->pre_lock);
1725}
1726
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727/* must be called with out->lock locked */
1728static int send_offload_cmd_l(struct stream_out* out, int command)
1729{
1730 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1731
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001732 if (!cmd) {
1733 ALOGE("failed to allocate mem for command 0x%x", command);
1734 return -ENOMEM;
1735 }
1736
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 ALOGVV("%s %d", __func__, command);
1738
1739 cmd->cmd = command;
1740 list_add_tail(&out->offload_cmd_list, &cmd->node);
1741 pthread_cond_signal(&out->offload_cond);
1742 return 0;
1743}
1744
1745/* must be called iwth out->lock locked */
1746static void stop_compressed_output_l(struct stream_out *out)
1747{
1748 out->offload_state = OFFLOAD_STATE_IDLE;
1749 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001750 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 if (out->compr != NULL) {
1752 compress_stop(out->compr);
1753 while (out->offload_thread_blocked) {
1754 pthread_cond_wait(&out->cond, &out->lock);
1755 }
1756 }
1757}
1758
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001759bool is_offload_usecase(audio_usecase_t uc_id)
1760{
1761 unsigned int i;
1762 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1763 if (uc_id == offload_usecases[i])
1764 return true;
1765 }
1766 return false;
1767}
1768
vivek mehta446c3962015-09-14 10:57:35 -07001769static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001770{
vivek mehta446c3962015-09-14 10:57:35 -07001771 audio_usecase_t ret_uc = USECASE_INVALID;
1772 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001773 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001774 if (!adev->multi_offload_enable) {
1775 if (is_direct_pcm)
1776 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1777 else
1778 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001779
vivek mehta446c3962015-09-14 10:57:35 -07001780 pthread_mutex_lock(&adev->lock);
1781 if (get_usecase_from_list(adev, ret_uc) != NULL)
1782 ret_uc = USECASE_INVALID;
1783 pthread_mutex_unlock(&adev->lock);
1784
1785 return ret_uc;
1786 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001787
1788 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001789 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1790 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1791 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1792 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001793 break;
1794 }
1795 }
vivek mehta446c3962015-09-14 10:57:35 -07001796
1797 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1798 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001799}
1800
1801static void free_offload_usecase(struct audio_device *adev,
1802 audio_usecase_t uc_id)
1803{
vivek mehta446c3962015-09-14 10:57:35 -07001804 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001805 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001806
1807 if (!adev->multi_offload_enable)
1808 return;
1809
1810 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1811 if (offload_usecases[offload_uc_index] == uc_id) {
1812 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001813 break;
1814 }
1815 }
1816 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1817}
1818
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819static void *offload_thread_loop(void *context)
1820{
1821 struct stream_out *out = (struct stream_out *) context;
1822 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001823 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1826 set_sched_policy(0, SP_FOREGROUND);
1827 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1828
1829 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001830 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 for (;;) {
1832 struct offload_cmd *cmd = NULL;
1833 stream_callback_event_t event;
1834 bool send_callback = false;
1835
1836 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1837 __func__, list_empty(&out->offload_cmd_list),
1838 out->offload_state);
1839 if (list_empty(&out->offload_cmd_list)) {
1840 ALOGV("%s SLEEPING", __func__);
1841 pthread_cond_wait(&out->offload_cond, &out->lock);
1842 ALOGV("%s RUNNING", __func__);
1843 continue;
1844 }
1845
1846 item = list_head(&out->offload_cmd_list);
1847 cmd = node_to_item(item, struct offload_cmd, node);
1848 list_remove(item);
1849
1850 ALOGVV("%s STATE %d CMD %d out->compr %p",
1851 __func__, out->offload_state, cmd->cmd, out->compr);
1852
1853 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1854 free(cmd);
1855 break;
1856 }
1857
1858 if (out->compr == NULL) {
1859 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001860 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001861 pthread_cond_signal(&out->cond);
1862 continue;
1863 }
1864 out->offload_thread_blocked = true;
1865 pthread_mutex_unlock(&out->lock);
1866 send_callback = false;
1867 switch(cmd->cmd) {
1868 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001869 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001871 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001872 send_callback = true;
1873 event = STREAM_CBK_EVENT_WRITE_READY;
1874 break;
1875 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001876 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301877 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001878 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301879 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001880 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301881 if (ret < 0)
1882 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301883 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301884 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001885 compress_drain(out->compr);
1886 else
1887 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301888 if (ret != -ENETRESET) {
1889 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301890 pthread_mutex_lock(&out->lock);
1891 out->send_new_metadata = 1;
1892 out->send_next_track_params = true;
1893 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301894 event = STREAM_CBK_EVENT_DRAIN_READY;
1895 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1896 } else
1897 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 break;
1899 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001900 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001901 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001902 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001903 send_callback = true;
1904 event = STREAM_CBK_EVENT_DRAIN_READY;
1905 break;
1906 default:
1907 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1908 break;
1909 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001910 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001911 out->offload_thread_blocked = false;
1912 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001913 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001914 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001915 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001916 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917 free(cmd);
1918 }
1919
1920 pthread_cond_signal(&out->cond);
1921 while (!list_empty(&out->offload_cmd_list)) {
1922 item = list_head(&out->offload_cmd_list);
1923 list_remove(item);
1924 free(node_to_item(item, struct offload_cmd, node));
1925 }
1926 pthread_mutex_unlock(&out->lock);
1927
1928 return NULL;
1929}
1930
1931static int create_offload_callback_thread(struct stream_out *out)
1932{
1933 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1934 list_init(&out->offload_cmd_list);
1935 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1936 offload_thread_loop, out);
1937 return 0;
1938}
1939
1940static int destroy_offload_callback_thread(struct stream_out *out)
1941{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001942 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 stop_compressed_output_l(out);
1944 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1945
1946 pthread_mutex_unlock(&out->lock);
1947 pthread_join(out->offload_thread, (void **) NULL);
1948 pthread_cond_destroy(&out->offload_cond);
1949
1950 return 0;
1951}
1952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953static int stop_output_stream(struct stream_out *out)
1954{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301955 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 struct audio_usecase *uc_info;
1957 struct audio_device *adev = out->dev;
1958
Eric Laurent994a6932013-07-17 11:51:42 -07001959 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001960 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 uc_info = get_usecase_from_list(adev, out->usecase);
1962 if (uc_info == NULL) {
1963 ALOGE("%s: Could not find the usecase (%d) in the list",
1964 __func__, out->usecase);
1965 return -EINVAL;
1966 }
1967
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001968 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301969 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001970 if (adev->visualizer_stop_output != NULL)
1971 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001972
1973 audio_extn_dts_remove_state_notifier_node(out->usecase);
1974
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001975 if (adev->offload_effects_stop_output != NULL)
1976 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1977 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001978
Eric Laurent150dbfe2013-02-27 14:31:02 -08001979 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981
1982 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001983 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001985 list_remove(&uc_info->list);
1986 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001988 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301989 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001990 ALOGV("Disable passthrough , reset mixer to pcm");
1991 /* NO_PASSTHROUGH */
1992 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001993 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001994 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1995 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001996
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301997 /* Must be called after removing the usecase from list */
1998 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301999 audio_extn_keep_alive_start();
2000
Eric Laurent994a6932013-07-17 11:51:42 -07002001 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 return ret;
2003}
2004
2005int start_output_stream(struct stream_out *out)
2006{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 struct audio_usecase *uc_info;
2009 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302010 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002012 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2013 ret = -EINVAL;
2014 goto error_config;
2015 }
2016
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302017 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2018 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2019 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302020
Naresh Tanniru80659832014-06-04 18:17:56 +05302021 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302022 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302023 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302024 goto error_config;
2025 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302026
Eric Laurentb23d5282013-05-14 15:27:20 -07002027 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 if (out->pcm_device_id < 0) {
2029 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2030 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002031 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002032 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 }
2034
2035 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002036
2037 if (!uc_info) {
2038 ret = -ENOMEM;
2039 goto error_config;
2040 }
2041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 uc_info->id = out->usecase;
2043 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002044 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002045 uc_info->devices = out->devices;
2046 uc_info->in_snd_device = SND_DEVICE_NONE;
2047 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002048 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302050 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2051 adev->perf_lock_opts,
2052 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302053
2054 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2055 audio_extn_keep_alive_stop();
2056 if (audio_extn_passthru_is_enabled() &&
2057 audio_extn_passthru_is_passthrough_stream(out)) {
2058 audio_extn_passthru_on_start(out);
2059 audio_extn_passthru_update_stream_configuration(adev, out);
2060 }
2061 }
2062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 select_devices(adev, out->usecase);
2064
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002065 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2066 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002067 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002068 unsigned int flags = PCM_OUT;
2069 unsigned int pcm_open_retry_count = 0;
2070 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2071 flags |= PCM_MMAP | PCM_NOIRQ;
2072 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002073 } else if (out->realtime) {
2074 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002075 } else
2076 flags |= PCM_MONOTONIC;
2077
2078 while (1) {
2079 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2080 flags, &out->config);
2081 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2082 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2083 if (out->pcm != NULL) {
2084 pcm_close(out->pcm);
2085 out->pcm = NULL;
2086 }
2087 if (pcm_open_retry_count-- == 0) {
2088 ret = -EIO;
2089 goto error_open;
2090 }
2091 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2092 continue;
2093 }
2094 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002096
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002097 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2098 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002099
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002100 ALOGV("%s: pcm_prepare", __func__);
2101 if (pcm_is_ready(out->pcm)) {
2102 ret = pcm_prepare(out->pcm);
2103 if (ret < 0) {
2104 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2105 pcm_close(out->pcm);
2106 out->pcm = NULL;
2107 goto error_open;
2108 }
2109 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002111 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2112 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002114 out->compr = compress_open(adev->snd_card,
2115 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 COMPRESS_IN, &out->compr_config);
2117 if (out->compr && !is_compress_ready(out->compr)) {
2118 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2119 compress_close(out->compr);
2120 out->compr = NULL;
2121 ret = -EIO;
2122 goto error_open;
2123 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302124 /* compress_open sends params of the track, so reset the flag here */
2125 out->is_compr_metadata_avail = false;
2126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 if (out->offload_callback)
2128 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002129
Fred Oh3f43e742015-03-04 18:42:34 -08002130 /* Since small bufs uses blocking writes, a write will be blocked
2131 for the default max poll time (20s) in the event of an SSR.
2132 Reduce the poll time to observe and deal with SSR faster.
2133 */
Ashish Jain5106d362016-05-11 19:23:33 +05302134 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002135 compress_set_max_poll_wait(out->compr, 1000);
2136 }
2137
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002138 audio_extn_dts_create_state_notifier_node(out->usecase);
2139 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2140 popcount(out->channel_mask),
2141 out->playback_started);
2142
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002143#ifdef DS1_DOLBY_DDP_ENABLED
2144 if (audio_extn_is_dolby_format(out->format))
2145 audio_extn_dolby_send_ddp_endp_params(adev);
2146#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302147 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002148 if (adev->visualizer_start_output != NULL)
2149 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2150 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302151 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002152 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002155
2156 if (ret == 0) {
2157 register_out_stream(out);
2158 if (out->realtime) {
2159 ret = pcm_start(out->pcm);
2160 if (ret < 0)
2161 goto error_open;
2162 }
2163 }
2164
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302165 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002166 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002167
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002168 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302170 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002172error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302173 /*
2174 * sleep 50ms to allow sufficient time for kernel
2175 * drivers to recover incases like SSR.
2176 */
2177 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002178 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179}
2180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181static int check_input_parameters(uint32_t sample_rate,
2182 audio_format_t format,
2183 int channel_count)
2184{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002185 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302187 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2188 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2189 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002190 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302191 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002192
2193 switch (channel_count) {
2194 case 1:
2195 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302196 case 3:
2197 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002198 case 6:
2199 break;
2200 default:
2201 ret = -EINVAL;
2202 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203
2204 switch (sample_rate) {
2205 case 8000:
2206 case 11025:
2207 case 12000:
2208 case 16000:
2209 case 22050:
2210 case 24000:
2211 case 32000:
2212 case 44100:
2213 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302214 case 96000:
2215 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216 break;
2217 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002218 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 }
2220
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002221 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222}
2223
2224static size_t get_input_buffer_size(uint32_t sample_rate,
2225 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002226 int channel_count,
2227 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228{
2229 size_t size = 0;
2230
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002231 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2232 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002234 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002235 if (is_low_latency)
2236 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302237
2238 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002240 /* make sure the size is multiple of 32 bytes
2241 * At 48 kHz mono 16-bit PCM:
2242 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2243 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2244 */
2245 size += 0x1f;
2246 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002247
2248 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249}
2250
Ashish Jain058165c2016-09-28 23:18:48 +05302251static size_t get_output_period_size(uint32_t sample_rate,
2252 audio_format_t format,
2253 int channel_count,
2254 int duration /*in millisecs*/)
2255{
2256 size_t size = 0;
2257 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2258
2259 if ((duration == 0) || (sample_rate == 0) ||
2260 (bytes_per_sample == 0) || (channel_count == 0)) {
2261 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2262 bytes_per_sample, channel_count);
2263 return -EINVAL;
2264 }
2265
2266 size = (sample_rate *
2267 duration *
2268 bytes_per_sample *
2269 channel_count) / 1000;
2270 /*
2271 * To have same PCM samples for all channels, the buffer size requires to
2272 * be multiple of (number of channels * bytes per sample)
2273 * For writes to succeed, the buffer must be written at address which is multiple of 32
2274 */
2275 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2276
2277 return (size/(channel_count * bytes_per_sample));
2278}
2279
Ashish Jain5106d362016-05-11 19:23:33 +05302280static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2281{
2282 uint64_t actual_frames_rendered = 0;
2283 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2284
2285 /* This adjustment accounts for buffering after app processor.
2286 * It is based on estimated DSP latency per use case, rather than exact.
2287 */
2288 int64_t platform_latency = platform_render_latency(out->usecase) *
2289 out->sample_rate / 1000000LL;
2290
2291 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2292 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2293 * hence only estimate.
2294 */
2295 int64_t signed_frames = out->written - kernel_buffer_size;
2296
2297 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2298
2299 if (signed_frames > 0)
2300 actual_frames_rendered = signed_frames;
2301
2302 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2303 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2304 (long long int)out->written, (int)kernel_buffer_size,
2305 audio_bytes_per_sample(out->compr_config.codec->format),
2306 popcount(out->channel_mask));
2307
2308 return actual_frames_rendered;
2309}
2310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316}
2317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002318static int out_set_sample_rate(struct audio_stream *stream __unused,
2319 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320{
2321 return -ENOSYS;
2322}
2323
2324static size_t out_get_buffer_size(const struct audio_stream *stream)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002328 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002330 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2331 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302332 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302333 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002334
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002335 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002336 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337}
2338
2339static uint32_t out_get_channels(const struct audio_stream *stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342
2343 return out->channel_mask;
2344}
2345
2346static audio_format_t out_get_format(const struct audio_stream *stream)
2347{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 struct stream_out *out = (struct stream_out *)stream;
2349
2350 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351}
2352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002353static int out_set_format(struct audio_stream *stream __unused,
2354 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355{
2356 return -ENOSYS;
2357}
2358
2359static int out_standby(struct audio_stream *stream)
2360{
2361 struct stream_out *out = (struct stream_out *)stream;
2362 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302364 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2365 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002367 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002369 if (adev->adm_deregister_stream)
2370 adev->adm_deregister_stream(adev->adm_data, out->handle);
2371
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002372 if (is_offload_usecase(out->usecase))
2373 stop_compressed_output_l(out);
2374
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002375 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002377 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2378 voice_extn_compress_voip_close_output_stream(stream);
2379 pthread_mutex_unlock(&adev->lock);
2380 pthread_mutex_unlock(&out->lock);
2381 ALOGD("VOIP output entered standby");
2382 return 0;
2383 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 if (out->pcm) {
2385 pcm_close(out->pcm);
2386 out->pcm = NULL;
2387 }
2388 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002389 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302390 out->send_next_track_params = false;
2391 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002392 out->gapless_mdata.encoder_delay = 0;
2393 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 if (out->compr != NULL) {
2395 compress_close(out->compr);
2396 out->compr = NULL;
2397 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002398 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002400 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 }
2402 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302403 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404 return 0;
2405}
2406
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002407static int out_dump(const struct audio_stream *stream __unused,
2408 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409{
2410 return 0;
2411}
2412
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002413static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2414{
2415 int ret = 0;
2416 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002417
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002418 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002419 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002420 return -EINVAL;
2421 }
2422
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302423 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002424
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002425 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2426 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302427 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002428 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002429 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2430 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302431 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002432 }
2433
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002434 ALOGV("%s new encoder delay %u and padding %u", __func__,
2435 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2436
2437 return 0;
2438}
2439
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002440static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2441{
2442 return out == adev->primary_output || out == adev->voice_tx_output;
2443}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2446{
2447 struct stream_out *out = (struct stream_out *)stream;
2448 struct audio_device *adev = out->dev;
2449 struct str_parms *parms;
2450 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002451 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452
sangwoobc677242013-08-08 16:53:43 +09002453 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002454 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302456 if (!parms)
2457 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002458 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2459 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002461 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002462 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002464 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002465 * When HDMI cable is unplugged the music playback is paused and
2466 * the policy manager sends routing=0. But the audioflinger continues
2467 * to write data until standby time (3sec). As the HDMI core is
2468 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002469 * Avoid this by routing audio to speaker until standby.
2470 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002471 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2472 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302473 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002474 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2475 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002476 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302477 /*
2478 * When A2DP is disconnected the
2479 * music playback is paused and the policy manager sends routing=0
2480 * But the audioflingercontinues to write data until standby time
2481 * (3sec). As BT is turned off, the write gets blocked.
2482 * Avoid this by routing audio to speaker until standby.
2483 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002484 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302485 (val == AUDIO_DEVICE_NONE)) {
2486 val = AUDIO_DEVICE_OUT_SPEAKER;
2487 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302488 /* To avoid a2dp to sco overlapping force route BT usecases
2489 * to speaker based on Phone state
2490 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002491 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302492 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2493 (adev->mode == AUDIO_MODE_IN_CALL))) {
2494 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2495 val = AUDIO_DEVICE_OUT_SPEAKER;
2496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497 /*
2498 * select_devices() call below switches all the usecases on the same
2499 * backend to the new device. Refer to check_usecases_codec_backend() in
2500 * the select_devices(). But how do we undo this?
2501 *
2502 * For example, music playback is active on headset (deep-buffer usecase)
2503 * and if we go to ringtones and select a ringtone, low-latency usecase
2504 * will be started on headset+speaker. As we can't enable headset+speaker
2505 * and headset devices at the same time, select_devices() switches the music
2506 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2507 * So when the ringtone playback is completed, how do we undo the same?
2508 *
2509 * We are relying on the out_set_parameters() call on deep-buffer output,
2510 * once the ringtone playback is ended.
2511 * NOTE: We should not check if the current devices are same as new devices.
2512 * Because select_devices() must be called to switch back the music
2513 * playback to headset.
2514 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002515 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002516 audio_devices_t new_dev = val;
2517 bool same_dev = out->devices == new_dev;
2518 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002519
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002520 if (output_drives_call(adev, out)) {
2521 if(!voice_is_in_call(adev)) {
2522 if (adev->mode == AUDIO_MODE_IN_CALL) {
2523 adev->current_call_output = out;
2524 ret = voice_start_call(adev);
2525 }
2526 } else {
2527 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002528 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002529 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002530 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002531
2532 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002533 if (!same_dev) {
2534 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302535 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2536 adev->perf_lock_opts,
2537 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002538 if (adev->adm_on_routing_change)
2539 adev->adm_on_routing_change(adev->adm_data,
2540 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002541 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002542 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302543 if (!same_dev)
2544 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002545 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002546 }
2547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002549 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002551
2552 if (out == adev->primary_output) {
2553 pthread_mutex_lock(&adev->lock);
2554 audio_extn_set_parameters(adev, parms);
2555 pthread_mutex_unlock(&adev->lock);
2556 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002557 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002558 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002560
2561 audio_extn_dts_create_state_notifier_node(out->usecase);
2562 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2563 popcount(out->channel_mask),
2564 out->playback_started);
2565
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002566 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002567 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302570error:
Eric Laurent994a6932013-07-17 11:51:42 -07002571 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 return ret;
2573}
2574
2575static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2576{
2577 struct stream_out *out = (struct stream_out *)stream;
2578 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002579 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 char value[256];
2581 struct str_parms *reply = str_parms_create();
2582 size_t i, j;
2583 int ret;
2584 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002585
2586 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002587 if (reply) {
2588 str_parms_destroy(reply);
2589 }
2590 if (query) {
2591 str_parms_destroy(query);
2592 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002593 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2594 return NULL;
2595 }
2596
Eric Laurent994a6932013-07-17 11:51:42 -07002597 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2599 if (ret >= 0) {
2600 value[0] = '\0';
2601 i = 0;
2602 while (out->supported_channel_masks[i] != 0) {
2603 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2604 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2605 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002606 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002608 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 first = false;
2610 break;
2611 }
2612 }
2613 i++;
2614 }
2615 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2616 str = str_parms_to_str(reply);
2617 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002618 voice_extn_out_get_parameters(out, query, reply);
2619 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002620 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002621 free(str);
2622 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002625
Alexy Joseph62142aa2015-11-16 15:10:34 -08002626
2627 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2628 if (ret >= 0) {
2629 value[0] = '\0';
2630 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2631 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302632 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002633 } else {
2634 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302635 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002636 }
2637 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002638 if (str)
2639 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002640 str = str_parms_to_str(reply);
2641 }
2642
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002643 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2644 if (ret >= 0) {
2645 value[0] = '\0';
2646 i = 0;
2647 first = true;
2648 while (out->supported_formats[i] != 0) {
2649 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2650 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2651 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002652 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002653 }
2654 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2655 first = false;
2656 break;
2657 }
2658 }
2659 i++;
2660 }
2661 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002662 if (str)
2663 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002664 str = str_parms_to_str(reply);
2665 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002666
2667 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2668 if (ret >= 0) {
2669 value[0] = '\0';
2670 i = 0;
2671 first = true;
2672 while (out->supported_sample_rates[i] != 0) {
2673 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2674 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2675 if (!first) {
2676 strlcat(value, "|", sizeof(value));
2677 }
2678 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2679 first = false;
2680 break;
2681 }
2682 }
2683 i++;
2684 }
2685 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2686 if (str)
2687 free(str);
2688 str = str_parms_to_str(reply);
2689 }
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 str_parms_destroy(query);
2692 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002693 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 return str;
2695}
2696
2697static uint32_t out_get_latency(const struct audio_stream_out *stream)
2698{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002699 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002701 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
Alexy Josephaa54c872014-12-03 02:46:47 -08002703 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002704 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002705 } else if (out->realtime) {
2706 // since the buffer won't be filled up faster than realtime,
2707 // return a smaller number
2708 if (out->config.rate)
2709 period_ms = (out->af_period_multiplier * out->config.period_size *
2710 1000) / (out->config.rate);
2711 else
2712 period_ms = 0;
2713 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002714 } else {
2715 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002716 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002717 }
2718
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302719 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002720 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721}
2722
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302723static float AmpToDb(float amplification)
2724{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302725 float db = DSD_VOLUME_MIN_DB;
2726 if (amplification > 0) {
2727 db = 20 * log10(amplification);
2728 if(db < DSD_VOLUME_MIN_DB)
2729 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302730 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302731 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302732}
2733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734static int out_set_volume(struct audio_stream_out *stream, float left,
2735 float right)
2736{
Eric Laurenta9024de2013-04-04 09:19:12 -07002737 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 int volume[2];
2739
Eric Laurenta9024de2013-04-04 09:19:12 -07002740 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2741 /* only take left channel into account: the API is for stereo anyway */
2742 out->muted = (left == 0.0f);
2743 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002744 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302745 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002746 /*
2747 * Set mute or umute on HDMI passthrough stream.
2748 * Only take left channel into account.
2749 * Mute is 0 and unmute 1
2750 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302751 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302752 } else if (out->format == AUDIO_FORMAT_DSD){
2753 char mixer_ctl_name[128] = "DSD Volume";
2754 struct audio_device *adev = out->dev;
2755 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2756
2757 if (!ctl) {
2758 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2759 __func__, mixer_ctl_name);
2760 return -EINVAL;
2761 }
2762 volume[0] = (int)(AmpToDb(left));
2763 volume[1] = (int)(AmpToDb(right));
2764 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2765 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002766 } else {
2767 char mixer_ctl_name[128];
2768 struct audio_device *adev = out->dev;
2769 struct mixer_ctl *ctl;
2770 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002771 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002773 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2774 "Compress Playback %d Volume", pcm_device_id);
2775 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2776 if (!ctl) {
2777 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2778 __func__, mixer_ctl_name);
2779 return -EINVAL;
2780 }
2781 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2782 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2783 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2784 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002785 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002786 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 return -ENOSYS;
2789}
2790
2791static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2792 size_t bytes)
2793{
2794 struct stream_out *out = (struct stream_out *)stream;
2795 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302796 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002797 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002799 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302800
Naresh Tanniru80659832014-06-04 18:17:56 +05302801 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002802
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302803 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302804 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302805 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2806 pthread_mutex_unlock(&out->lock);
2807 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302808 } else {
2809 /* increase written size during SSR to avoid mismatch
2810 * with the written frames count in AF
2811 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002812 // bytes per frame
2813 size_t bpf = audio_bytes_per_sample(out->format) *
2814 audio_channel_count_from_out_mask(out->channel_mask);
2815 if (bpf != 0)
2816 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302817 ALOGD(" %s: sound card is not active/SSR state", __func__);
2818 ret= -EIO;
2819 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302820 }
2821 }
2822
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302823 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302824 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2825 if (audio_bytes_per_sample(out->format) != 0)
2826 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2827 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302828 goto exit;
2829 }
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002832 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002833 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002834 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2835 ret = voice_extn_compress_voip_start_output_stream(out);
2836 else
2837 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002838 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002841 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 goto exit;
2843 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002844
2845 if (last_known_cal_step != -1) {
2846 ALOGD("%s: retry previous failed cal level set", __func__);
2847 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850
Ashish Jain81eb2a82015-05-13 10:52:34 +05302851 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002852 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302853 adev->is_channel_status_set = true;
2854 }
2855
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002856 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002857 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002858 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002859 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002860 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2861 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302862 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2863 ALOGD("copl(%p):send next track params in gapless", out);
2864 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2865 out->send_next_track_params = false;
2866 out->is_compr_metadata_avail = false;
2867 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002868 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302869 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302870 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002871
Ashish Jain83a6cc22016-06-28 14:34:17 +05302872 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302873 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302874 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302875 pthread_mutex_unlock(&out->lock);
2876 return -EINVAL;
2877 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302878 audio_format_t dst_format = out->hal_op_format;
2879 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302880
2881 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2882 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2883
Ashish Jain83a6cc22016-06-28 14:34:17 +05302884 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302885 dst_format,
2886 buffer,
2887 src_format,
2888 frames);
2889
Ashish Jain83a6cc22016-06-28 14:34:17 +05302890 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302891 bytes_to_write);
2892
2893 /*Convert written bytes in audio flinger format*/
2894 if (ret > 0)
2895 ret = ((ret * format_to_bitwidth_table[out->format]) /
2896 format_to_bitwidth_table[dst_format]);
2897 }
2898 } else
2899 ret = compress_write(out->compr, buffer, bytes);
2900
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302901 if (ret < 0)
2902 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302903 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302904 /*msg to cb thread only if non blocking write is enabled*/
2905 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302906 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302908 } else if (-ENETRESET == ret) {
2909 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2910 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2911 pthread_mutex_unlock(&out->lock);
2912 out_standby(&out->stream.common);
2913 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 }
Ashish Jain5106d362016-05-11 19:23:33 +05302915 if ( ret == (ssize_t)bytes && !out->non_blocking)
2916 out->written += bytes;
2917
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302918 /* Call compr start only when non-zero bytes of data is there to be rendered */
2919 if (!out->playback_started && ret > 0) {
2920 int status = compress_start(out->compr);
2921 if (status < 0) {
2922 ret = status;
2923 ALOGE("%s: compr start failed with err %d", __func__, errno);
2924 goto exit;
2925 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002926 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 out->playback_started = 1;
2928 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002929
2930 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2931 popcount(out->channel_mask),
2932 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 }
2934 pthread_mutex_unlock(&out->lock);
2935 return ret;
2936 } else {
2937 if (out->pcm) {
2938 if (out->muted)
2939 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002940
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302941 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002942
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002943 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002944
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002945 if (out->config.rate)
2946 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2947 out->config.rate;
2948
2949 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2950
2951 request_out_focus(out, ns);
2952
2953 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002954 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002955 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302956 out->convert_buffer != NULL) {
2957
2958 memcpy_by_audio_format(out->convert_buffer,
2959 out->hal_op_format,
2960 buffer,
2961 out->hal_ip_format,
2962 out->config.period_size * out->config.channels);
2963
2964 ret = pcm_write(out->pcm, out->convert_buffer,
2965 (out->config.period_size *
2966 out->config.channels *
2967 format_to_bitwidth_table[out->hal_op_format]));
2968 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002969 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302970 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002971
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002972 release_out_focus(out);
2973
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302974 if (ret < 0)
2975 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302976 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2977 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2978 else
2979 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 }
2982
2983exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302984 /* ToDo: There may be a corner case when SSR happens back to back during
2985 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302986 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302987 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302988 }
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 pthread_mutex_unlock(&out->lock);
2991
2992 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002993 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002994 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302995 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302996 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302997 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302998 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302999 out->standby = true;
3000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303002 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3003 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3004 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 }
3006 return bytes;
3007}
3008
3009static int out_get_render_position(const struct audio_stream_out *stream,
3010 uint32_t *dsp_frames)
3011{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303013 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003014
3015 if (dsp_frames == NULL)
3016 return -EINVAL;
3017
3018 *dsp_frames = 0;
3019 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003020 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303021
3022 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3023 * this operation and adev_close_output_stream(where out gets reset).
3024 */
3025 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3026 *dsp_frames = get_actual_pcm_frames_rendered(out);
3027 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3028 return 0;
3029 }
3030
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003031 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303032 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303033 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303035 if (ret < 0)
3036 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303038 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 }
3040 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303041 if (-ENETRESET == ret) {
3042 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3043 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3044 return -EINVAL;
3045 } else if(ret < 0) {
3046 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3047 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303048 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3049 /*
3050 * Handle corner case where compress session is closed during SSR
3051 * and timestamp is queried
3052 */
3053 ALOGE(" ERROR: sound card not active, return error");
3054 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303055 } else {
3056 return 0;
3057 }
Zhou Song32a556e2015-05-05 10:46:56 +08003058 } else if (audio_is_linear_pcm(out->format)) {
3059 *dsp_frames = out->written;
3060 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 } else
3062 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003065static int out_add_audio_effect(const struct audio_stream *stream __unused,
3066 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067{
3068 return 0;
3069}
3070
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003071static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3072 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073{
3074 return 0;
3075}
3076
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003077static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3078 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079{
3080 return -EINVAL;
3081}
3082
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003083static int out_get_presentation_position(const struct audio_stream_out *stream,
3084 uint64_t *frames, struct timespec *timestamp)
3085{
3086 struct stream_out *out = (struct stream_out *)stream;
3087 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003088 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003089
Ashish Jain5106d362016-05-11 19:23:33 +05303090 /* below piece of code is not guarded against any lock because audioFliner serializes
3091 * this operation and adev_close_output_stream( where out gets reset).
3092 */
3093 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3094 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3095 *frames = get_actual_pcm_frames_rendered(out);
3096 /* this is the best we can do */
3097 clock_gettime(CLOCK_MONOTONIC, timestamp);
3098 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3099 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3100 return 0;
3101 }
3102
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003103 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003104
Ashish Jain5106d362016-05-11 19:23:33 +05303105 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3106 ret = compress_get_tstamp(out->compr, &dsp_frames,
3107 &out->sample_rate);
3108 ALOGVV("%s rendered frames %ld sample_rate %d",
3109 __func__, dsp_frames, out->sample_rate);
3110 *frames = dsp_frames;
3111 if (ret < 0)
3112 ret = -errno;
3113 if (-ENETRESET == ret) {
3114 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3115 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3116 ret = -EINVAL;
3117 } else
3118 ret = 0;
3119 /* this is the best we can do */
3120 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003121 } else {
3122 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003123 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003124 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3125 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003126 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003127 // This adjustment accounts for buffering after app processor.
3128 // It is based on estimated DSP latency per use case, rather than exact.
3129 signed_frames -=
3130 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3131
Eric Laurent949a0892013-09-20 09:20:13 -07003132 // It would be unusual for this value to be negative, but check just in case ...
3133 if (signed_frames >= 0) {
3134 *frames = signed_frames;
3135 ret = 0;
3136 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003137 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303138 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3139 *frames = out->written;
3140 clock_gettime(CLOCK_MONOTONIC, timestamp);
3141 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003142 }
3143 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003144 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003145 return ret;
3146}
3147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148static int out_set_callback(struct audio_stream_out *stream,
3149 stream_callback_t callback, void *cookie)
3150{
3151 struct stream_out *out = (struct stream_out *)stream;
3152
3153 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003154 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003155 out->offload_callback = callback;
3156 out->offload_cookie = cookie;
3157 pthread_mutex_unlock(&out->lock);
3158 return 0;
3159}
3160
3161static int out_pause(struct audio_stream_out* stream)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164 int status = -ENOSYS;
3165 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003166 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003167 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003168 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303170 struct audio_device *adev = out->dev;
3171 int snd_scard_state = get_snd_card_state(adev);
3172
3173 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3174 status = compress_pause(out->compr);
3175
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003176 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003177
Mingming Yin21854652016-04-13 11:54:02 -07003178 if (audio_extn_passthru_is_active()) {
3179 ALOGV("offload use case, pause passthru");
3180 audio_extn_passthru_on_pause(out);
3181 }
3182
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303183 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003184 audio_extn_dts_notify_playback_state(out->usecase, 0,
3185 out->sample_rate, popcount(out->channel_mask),
3186 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 }
3188 pthread_mutex_unlock(&out->lock);
3189 }
3190 return status;
3191}
3192
3193static int out_resume(struct audio_stream_out* stream)
3194{
3195 struct stream_out *out = (struct stream_out *)stream;
3196 int status = -ENOSYS;
3197 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003198 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003199 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003200 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003201 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303203 struct audio_device *adev = out->dev;
3204 int snd_scard_state = get_snd_card_state(adev);
3205
Mingming Yin21854652016-04-13 11:54:02 -07003206 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3207 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3208 pthread_mutex_lock(&out->dev->lock);
3209 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003210 pthread_mutex_unlock(&out->dev->lock);
3211 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303212 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003213 }
3214 if (!status) {
3215 out->offload_state = OFFLOAD_STATE_PLAYING;
3216 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303217 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003218 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3219 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220 }
3221 pthread_mutex_unlock(&out->lock);
3222 }
3223 return status;
3224}
3225
3226static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3227{
3228 struct stream_out *out = (struct stream_out *)stream;
3229 int status = -ENOSYS;
3230 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003231 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003232 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3234 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3235 else
3236 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3237 pthread_mutex_unlock(&out->lock);
3238 }
3239 return status;
3240}
3241
3242static int out_flush(struct audio_stream_out* stream)
3243{
3244 struct stream_out *out = (struct stream_out *)stream;
3245 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003246 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003247 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003248 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003249 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3250 stop_compressed_output_l(out);
3251 out->written = 0;
3252 } else {
3253 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3254 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003255 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003256 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 return 0;
3258 }
3259 return -ENOSYS;
3260}
3261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262/** audio_stream_in implementation **/
3263static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3264{
3265 struct stream_in *in = (struct stream_in *)stream;
3266
3267 return in->config.rate;
3268}
3269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003270static int in_set_sample_rate(struct audio_stream *stream __unused,
3271 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272{
3273 return -ENOSYS;
3274}
3275
3276static size_t in_get_buffer_size(const struct audio_stream *stream)
3277{
3278 struct stream_in *in = (struct stream_in *)stream;
3279
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003280 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3281 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003282 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3283 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003284
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003285 return in->config.period_size * in->af_period_multiplier *
3286 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287}
3288
3289static uint32_t in_get_channels(const struct audio_stream *stream)
3290{
3291 struct stream_in *in = (struct stream_in *)stream;
3292
3293 return in->channel_mask;
3294}
3295
3296static audio_format_t in_get_format(const struct audio_stream *stream)
3297{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003298 struct stream_in *in = (struct stream_in *)stream;
3299
3300 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301}
3302
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003303static int in_set_format(struct audio_stream *stream __unused,
3304 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
3306 return -ENOSYS;
3307}
3308
3309static int in_standby(struct audio_stream *stream)
3310{
3311 struct stream_in *in = (struct stream_in *)stream;
3312 struct audio_device *adev = in->dev;
3313 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303314 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3315 stream, in->usecase, use_case_table[in->usecase]);
3316
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003317 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003318 if (!in->standby && in->is_st_session) {
3319 ALOGD("%s: sound trigger pcm stop lab", __func__);
3320 audio_extn_sound_trigger_stop_lab(in);
3321 in->standby = 1;
3322 }
3323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003325 if (adev->adm_deregister_stream)
3326 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3327
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003328 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003330 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3331 voice_extn_compress_voip_close_input_stream(stream);
3332 ALOGD("VOIP input entered standby");
3333 } else {
3334 if (in->pcm) {
3335 pcm_close(in->pcm);
3336 in->pcm = NULL;
3337 }
3338 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003339 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003340 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 }
3342 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003343 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 return status;
3345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int in_dump(const struct audio_stream *stream __unused,
3348 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return 0;
3351}
3352
3353static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3354{
3355 struct stream_in *in = (struct stream_in *)stream;
3356 struct audio_device *adev = in->dev;
3357 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003359 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303361 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 parms = str_parms_create_str(kvpairs);
3363
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303364 if (!parms)
3365 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003366 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003367 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003368
3369 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3370 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 val = atoi(value);
3372 /* no audio source uses val == 0 */
3373 if ((in->source != val) && (val != 0)) {
3374 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003375 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3376 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3377 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003378 (in->config.rate == 8000 || in->config.rate == 16000 ||
3379 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003380 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003381 err = voice_extn_compress_voip_open_input_stream(in);
3382 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003383 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003384 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003385 }
3386 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 }
3388 }
3389
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003390 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3391 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003393 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 in->device = val;
3395 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003396 if (!in->standby && !in->is_st_session) {
3397 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003398 if (adev->adm_on_routing_change)
3399 adev->adm_on_routing_change(adev->adm_data,
3400 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003401 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 }
3404 }
3405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003407 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408
3409 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303410error:
Eric Laurent994a6932013-07-17 11:51:42 -07003411 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 return ret;
3413}
3414
3415static char* in_get_parameters(const struct audio_stream *stream,
3416 const char *keys)
3417{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003418 struct stream_in *in = (struct stream_in *)stream;
3419 struct str_parms *query = str_parms_create_str(keys);
3420 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003421 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003422
3423 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003424 if (reply) {
3425 str_parms_destroy(reply);
3426 }
3427 if (query) {
3428 str_parms_destroy(query);
3429 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003430 ALOGE("in_get_parameters: failed to create query or reply");
3431 return NULL;
3432 }
3433
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003434 ALOGV("%s: enter: keys - %s", __func__, keys);
3435
3436 voice_extn_in_get_parameters(in, query, reply);
3437
3438 str = str_parms_to_str(reply);
3439 str_parms_destroy(query);
3440 str_parms_destroy(reply);
3441
3442 ALOGV("%s: exit: returns - %s", __func__, str);
3443 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444}
3445
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003446static int in_set_gain(struct audio_stream_in *stream __unused,
3447 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448{
3449 return 0;
3450}
3451
3452static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3453 size_t bytes)
3454{
3455 struct stream_in *in = (struct stream_in *)stream;
3456 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303457 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303458 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303459 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003461 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303462
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003463 if (in->is_st_session) {
3464 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3465 /* Read from sound trigger HAL */
3466 audio_extn_sound_trigger_read(in, buffer, bytes);
3467 pthread_mutex_unlock(&in->lock);
3468 return bytes;
3469 }
3470
Ashish Jainbbce4322016-02-16 13:25:27 +05303471 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003472 ALOGD(" %s: sound card is not active/SSR state", __func__);
3473 ret= -EIO;;
3474 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303475 }
3476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003478 pthread_mutex_lock(&adev->lock);
3479 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3480 ret = voice_extn_compress_voip_start_input_stream(in);
3481 else
3482 ret = start_input_stream(in);
3483 pthread_mutex_unlock(&adev->lock);
3484 if (ret != 0) {
3485 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 }
3487 in->standby = 0;
3488 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003490 // what's the duration requested by the client?
3491 long ns = 0;
3492
3493 if (in->config.rate)
3494 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3495 in->config.rate;
3496
3497 request_in_focus(in, ns);
3498 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303501 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003502 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303503 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003504 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003505 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003506 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303507 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303509 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3510 if (bytes % 4 == 0) {
3511 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3512 int_buf_stream = buffer;
3513 for (size_t itt=0; itt < bytes/4 ; itt++) {
3514 int_buf_stream[itt] >>= 8;
3515 }
3516 } else {
3517 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3518 ret = -EINVAL;
3519 goto exit;
3520 }
3521 } if (ret < 0) {
3522 ret = -errno;
3523 }
3524 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 }
3526
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003527 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 /*
3530 * Instead of writing zeroes here, we could trust the hardware
3531 * to always provide zeroes when muted.
3532 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303533 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3534 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 memset(buffer, 0, bytes);
3536
3537exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303538 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303539 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003540 if (-ENETRESET == ret)
3541 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543 pthread_mutex_unlock(&in->lock);
3544
3545 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303546 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303547 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303548 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303549 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303550 in->standby = true;
3551 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303552 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003554 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303555 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303556 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 }
3558 return bytes;
3559}
3560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003561static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
3563 return 0;
3564}
3565
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003566static int add_remove_audio_effect(const struct audio_stream *stream,
3567 effect_handle_t effect,
3568 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003570 struct stream_in *in = (struct stream_in *)stream;
3571 int status = 0;
3572 effect_descriptor_t desc;
3573
3574 status = (*effect)->get_descriptor(effect, &desc);
3575 if (status != 0)
3576 return status;
3577
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003578 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003579 pthread_mutex_lock(&in->dev->lock);
3580 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3581 in->enable_aec != enable &&
3582 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3583 in->enable_aec = enable;
3584 if (!in->standby)
3585 select_devices(in->dev, in->usecase);
3586 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003587 if (in->enable_ns != enable &&
3588 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3589 in->enable_ns = enable;
3590 if (!in->standby)
3591 select_devices(in->dev, in->usecase);
3592 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003593 pthread_mutex_unlock(&in->dev->lock);
3594 pthread_mutex_unlock(&in->lock);
3595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 return 0;
3597}
3598
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003599static int in_add_audio_effect(const struct audio_stream *stream,
3600 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601{
Eric Laurent994a6932013-07-17 11:51:42 -07003602 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003603 return add_remove_audio_effect(stream, effect, true);
3604}
3605
3606static int in_remove_audio_effect(const struct audio_stream *stream,
3607 effect_handle_t effect)
3608{
Eric Laurent994a6932013-07-17 11:51:42 -07003609 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003610 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611}
3612
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303613int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 audio_io_handle_t handle,
3615 audio_devices_t devices,
3616 audio_output_flags_t flags,
3617 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003618 struct audio_stream_out **stream_out,
3619 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620{
3621 struct audio_device *adev = (struct audio_device *)dev;
3622 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303623 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003624 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303627
3628 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3629 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003630 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303631 return -EINVAL;
3632 }
3633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3635
Mingming Yin3a941d42016-02-17 18:08:05 -08003636 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3637 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303638 devices, flags, &out->stream);
3639
3640
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003641 if (!out) {
3642 return -ENOMEM;
3643 }
3644
Haynes Mathew George204045b2015-02-25 20:32:03 -08003645 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003646 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003647 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 if (devices == AUDIO_DEVICE_NONE)
3650 devices = AUDIO_DEVICE_OUT_SPEAKER;
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 out->flags = flags;
3653 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003654 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003655 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003656 out->sample_rate = config->sample_rate;
3657 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3658 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003659 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003660 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003661 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303662 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663
Mingming Yin3a941d42016-02-17 18:08:05 -08003664 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3665 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3666 pthread_mutex_lock(&adev->lock);
3667 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3668 ret = read_hdmi_sink_caps(out);
3669 pthread_mutex_unlock(&adev->lock);
3670 if (ret != 0) {
3671 if (ret == -ENOSYS) {
3672 /* ignore and go with default */
3673 ret = 0;
3674 } else {
3675 ALOGE("error reading hdmi sink caps");
3676 goto error_open;
3677 }
3678 }
3679 }
3680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003682 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303683 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3684 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003685 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3686 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3687
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003688 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003689 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3690 /*
3691 * Do not handle stereo output in Multi-channel cases
3692 * Stereo case is handled in normal playback path
3693 */
3694 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3695 ret = AUDIO_CHANNEL_OUT_STEREO;
3696 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003697
3698 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3699 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003700 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003701 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003702 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003703
3704 if (config->sample_rate == 0)
3705 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3706 if (config->channel_mask == 0)
3707 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003708 if (config->format == 0)
3709 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003710
3711 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003713 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3715 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003717 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003719 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3720 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003721 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003722 ret = voice_extn_compress_voip_open_output_stream(out);
3723 if (ret != 0) {
3724 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3725 __func__, ret);
3726 goto error_open;
3727 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003728 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3729 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003731 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3732 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3733 ALOGE("%s: Unsupported Offload information", __func__);
3734 ret = -EINVAL;
3735 goto error_open;
3736 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003737
Mingming Yin3a941d42016-02-17 18:08:05 -08003738 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003739 if(config->offload_info.format == 0)
3740 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003741 if (config->offload_info.sample_rate == 0)
3742 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003743 }
3744
Mingming Yin90310102013-11-13 16:57:00 -08003745 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303746 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003747 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748 ret = -EINVAL;
3749 goto error_open;
3750 }
3751
3752 out->compr_config.codec = (struct snd_codec *)
3753 calloc(1, sizeof(struct snd_codec));
3754
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003755 if (!out->compr_config.codec) {
3756 ret = -ENOMEM;
3757 goto error_open;
3758 }
3759
vivek mehta0ea887a2015-08-26 14:01:20 -07003760 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303761 out->stream.pause = out_pause;
3762 out->stream.flush = out_flush;
3763 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003764 out->usecase = get_offload_usecase(adev, true);
3765 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003766 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003767 out->stream.set_callback = out_set_callback;
3768 out->stream.pause = out_pause;
3769 out->stream.resume = out_resume;
3770 out->stream.drain = out_drain;
3771 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003772 out->usecase = get_offload_usecase(adev, false);
3773 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003774 }
vivek mehta446c3962015-09-14 10:57:35 -07003775
3776 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003777 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3778 config->format == 0 && config->sample_rate == 0 &&
3779 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003780 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003781 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3782 } else {
3783 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3784 ret = -EEXIST;
3785 goto error_open;
3786 }
vivek mehta446c3962015-09-14 10:57:35 -07003787 }
3788
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 if (config->offload_info.channel_mask)
3790 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003791 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003793 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003794 } else {
3795 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3796 ret = -EINVAL;
3797 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003798 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003799
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003800 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003801 out->sample_rate = config->offload_info.sample_rate;
3802
Mingming Yin3ee55c62014-08-04 14:23:35 -07003803 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003804
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303805 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3806 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3807 audio_extn_dolby_send_ddp_endp_params(adev);
3808 audio_extn_dolby_set_dmid(adev);
3809 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003811 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003812 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003813 out->compr_config.codec->bit_rate =
3814 config->offload_info.bit_rate;
3815 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303816 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303818 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003819 /*TODO: Do we need to change it for passthrough */
3820 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003821
Manish Dewangana6fc5442015-08-24 20:30:31 +05303822 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3823 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3824 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3825 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303826
3827 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3828 AUDIO_FORMAT_PCM) {
3829
3830 /*Based on platform support, configure appropriate alsa format for corresponding
3831 *hal input format.
3832 */
3833 out->compr_config.codec->format = hal_format_to_alsa(
3834 config->offload_info.format);
3835
Ashish Jain83a6cc22016-06-28 14:34:17 +05303836 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303837 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303838 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303839
3840 /*for direct PCM playback populate bit_width based on selected alsa format as
3841 *hal input format and alsa format might differ based on platform support.
3842 */
3843 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303844 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303845
3846 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3847
3848 /* Check if alsa session is configured with the same format as HAL input format,
3849 * if not then derive correct fragment size needed to accomodate the
3850 * conversion of HAL input format to alsa format.
3851 */
3852 audio_extn_utils_update_direct_pcm_fragment_size(out);
3853
3854 /*if hal input and output fragment size is different this indicates HAL input format is
3855 *not same as the alsa format
3856 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303857 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303858 /*Allocate a buffer to convert input data to the alsa configured format.
3859 *size of convert buffer is equal to the size required to hold one fragment size
3860 *worth of pcm data, this is because flinger does not write more than fragment_size
3861 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303862 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3863 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303864 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3865 ret = -ENOMEM;
3866 goto error_open;
3867 }
3868 }
3869 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3870 out->compr_config.fragment_size =
3871 audio_extn_passthru_get_buffer_size(&config->offload_info);
3872 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3873 } else {
3874 out->compr_config.fragment_size =
3875 platform_get_compress_offload_buffer_size(&config->offload_info);
3876 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3877 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003878
Amit Shekhar6f461b12014-08-01 14:52:58 -07003879 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303880 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003881
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003882 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3883 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003884
Alexy Josephaa54c872014-12-03 02:46:47 -08003885
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003886 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303887 out->send_next_track_params = false;
3888 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003889 out->offload_state = OFFLOAD_STATE_IDLE;
3890 out->playback_started = 0;
3891
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003892 audio_extn_dts_create_state_notifier_node(out->usecase);
3893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003894 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3895 __func__, config->offload_info.version,
3896 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303897
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303898 /* Check if DSD audio format is supported in codec
3899 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303900 */
3901
3902 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303903 (!platform_check_codec_dsd_support(adev->platform) ||
3904 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303905 ret = -EINVAL;
3906 goto error_open;
3907 }
3908
Ashish Jain5106d362016-05-11 19:23:33 +05303909 /* Disable gapless if any of the following is true
3910 * passthrough playback
3911 * AV playback
3912 * Direct PCM playback
3913 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303914 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303915 (config->format == AUDIO_FORMAT_DSD) ||
3916 config->offload_info.has_video ||
3917 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303918 check_and_set_gapless_mode(adev, false);
3919 } else
3920 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003921
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303922 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003923 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3924 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303925 if (config->format == AUDIO_FORMAT_DSD) {
3926 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3927 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3928 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003929
3930 create_offload_callback_thread(out);
3931
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003932 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303933 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003934 if (ret != 0) {
3935 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3936 __func__, ret);
3937 goto error_open;
3938 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003939 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3940 if (config->sample_rate == 0)
3941 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3942 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3943 config->sample_rate != 8000) {
3944 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3945 ret = -EINVAL;
3946 goto error_open;
3947 }
3948 out->sample_rate = config->sample_rate;
3949 out->config.rate = config->sample_rate;
3950 if (config->format == AUDIO_FORMAT_DEFAULT)
3951 config->format = AUDIO_FORMAT_PCM_16_BIT;
3952 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3953 config->format = AUDIO_FORMAT_PCM_16_BIT;
3954 ret = -EINVAL;
3955 goto error_open;
3956 }
3957 out->format = config->format;
3958 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3959 out->config = pcm_config_afe_proxy_playback;
3960 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003961 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05303962 unsigned int channels = 0;
3963 /*Update config params to default if not set by the caller*/
3964 if (config->sample_rate == 0)
3965 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3966 if (config->channel_mask == AUDIO_CHANNEL_NONE)
3967 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3968 if (config->format == AUDIO_FORMAT_DEFAULT)
3969 config->format = AUDIO_FORMAT_PCM_16_BIT;
3970
3971 channels = audio_channel_count_from_out_mask(out->channel_mask);
3972
Ashish Jain83a6cc22016-06-28 14:34:17 +05303973 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3974 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003975 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3976 out->flags);
3977 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303978 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3979 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3980 out->config = pcm_config_low_latency;
3981 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3982 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3983 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05303984 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
3985 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
3986 if (out->config.period_size <= 0) {
3987 ALOGE("Invalid configuration period size is not valid");
3988 ret = -EINVAL;
3989 goto error_open;
3990 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05303991 } else {
3992 /* primary path is the default path selected if no other outputs are available/suitable */
3993 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3994 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3995 }
3996 out->hal_ip_format = format = out->format;
3997 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3998 out->hal_op_format = pcm_format_to_hal(out->config.format);
3999 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4000 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004001 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304002 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304003 if (out->hal_ip_format != out->hal_op_format) {
4004 uint32_t buffer_size = out->config.period_size *
4005 format_to_bitwidth_table[out->hal_op_format] *
4006 out->config.channels;
4007 out->convert_buffer = calloc(1, buffer_size);
4008 if (out->convert_buffer == NULL){
4009 ALOGE("Allocation failed for convert buffer for size %d",
4010 out->compr_config.fragment_size);
4011 ret = -ENOMEM;
4012 goto error_open;
4013 }
4014 ALOGD("Convert buffer allocated of size %d", buffer_size);
4015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 }
4017
Ashish Jain83a6cc22016-06-28 14:34:17 +05304018 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4019 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4020
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004021 /* TODO remove this hardcoding and check why width is zero*/
4022 if (out->bit_width == 0)
4023 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004024 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
4025 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004026 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05304027 out->bit_width, out->channel_mask,
4028 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004029 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4030 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4031 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004032 if(adev->primary_output == NULL)
4033 adev->primary_output = out;
4034 else {
4035 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004036 ret = -EEXIST;
4037 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004038 }
4039 }
4040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 /* Check if this usecase is already existing */
4042 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004043 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4044 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004047 ret = -EEXIST;
4048 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 }
4050 pthread_mutex_unlock(&adev->lock);
4051
4052 out->stream.common.get_sample_rate = out_get_sample_rate;
4053 out->stream.common.set_sample_rate = out_set_sample_rate;
4054 out->stream.common.get_buffer_size = out_get_buffer_size;
4055 out->stream.common.get_channels = out_get_channels;
4056 out->stream.common.get_format = out_get_format;
4057 out->stream.common.set_format = out_set_format;
4058 out->stream.common.standby = out_standby;
4059 out->stream.common.dump = out_dump;
4060 out->stream.common.set_parameters = out_set_parameters;
4061 out->stream.common.get_parameters = out_get_parameters;
4062 out->stream.common.add_audio_effect = out_add_audio_effect;
4063 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4064 out->stream.get_latency = out_get_latency;
4065 out->stream.set_volume = out_set_volume;
4066 out->stream.write = out_write;
4067 out->stream.get_render_position = out_get_render_position;
4068 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004069 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004071 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004073 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004074 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075
4076 config->format = out->stream.common.get_format(&out->stream.common);
4077 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4078 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4079
4080 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304081 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004082 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004083
4084 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4085 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4086 popcount(out->channel_mask), out->playback_started);
4087
Eric Laurent994a6932013-07-17 11:51:42 -07004088 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004090
4091error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304092 if (out->convert_buffer)
4093 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004094 free(out);
4095 *stream_out = NULL;
4096 ALOGD("%s: exit: ret %d", __func__, ret);
4097 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098}
4099
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304100void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101 struct audio_stream_out *stream)
4102{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004103 struct stream_out *out = (struct stream_out *)stream;
4104 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004105 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004106
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304107 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4108
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004109 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304110 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004111 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304112 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004113 if(ret != 0)
4114 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4115 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004116 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004117 out_standby(&stream->common);
4118
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004119 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004120 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004121 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004122 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004123 if (out->compr_config.codec != NULL)
4124 free(out->compr_config.codec);
4125 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004126
Ashish Jain83a6cc22016-06-28 14:34:17 +05304127 if (out->convert_buffer != NULL) {
4128 free(out->convert_buffer);
4129 out->convert_buffer = NULL;
4130 }
4131
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004132 if (adev->voice_tx_output == out)
4133 adev->voice_tx_output = NULL;
4134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004135 pthread_cond_destroy(&out->cond);
4136 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004138 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139}
4140
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004141static void close_compress_sessions(struct audio_device *adev)
4142{
Mingming Yin7b762e72015-03-04 13:47:32 -08004143 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304144 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004145 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004146 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304147
4148 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004149 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304150 if (is_offload_usecase(usecase->id)) {
4151 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004152 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4153 out = usecase->stream.out;
4154 pthread_mutex_unlock(&adev->lock);
4155 out_standby(&out->stream.common);
4156 pthread_mutex_lock(&adev->lock);
4157 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304158 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004159 }
4160 pthread_mutex_unlock(&adev->lock);
4161}
4162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4164{
4165 struct audio_device *adev = (struct audio_device *)dev;
4166 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004168 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004169 int ret;
4170 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004172 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304175 if (!parms)
4176 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004177 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4178 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304179 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304180 if (strstr(snd_card_status, "OFFLINE")) {
4181 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304182 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004183 //close compress sessions on OFFLINE status
4184 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304185 } else if (strstr(snd_card_status, "ONLINE")) {
4186 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304187 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004188 //send dts hpx license if enabled
4189 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304190 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304191 }
4192
4193 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004194 status = voice_set_parameters(adev, parms);
4195 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004196 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004198 status = platform_set_parameters(adev->platform, parms);
4199 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004200 goto done;
4201
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4203 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004204 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4206 adev->bluetooth_nrec = true;
4207 else
4208 adev->bluetooth_nrec = false;
4209 }
4210
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004211 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4212 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4214 adev->screen_off = false;
4215 else
4216 adev->screen_off = true;
4217 }
4218
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004219 ret = str_parms_get_int(parms, "rotation", &val);
4220 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004221 bool reverse_speakers = false;
4222 switch(val) {
4223 // FIXME: note that the code below assumes that the speakers are in the correct placement
4224 // relative to the user when the device is rotated 90deg from its default rotation. This
4225 // assumption is device-specific, not platform-specific like this code.
4226 case 270:
4227 reverse_speakers = true;
4228 break;
4229 case 0:
4230 case 90:
4231 case 180:
4232 break;
4233 default:
4234 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004235 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004236 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004237 if (status == 0) {
4238 if (adev->speaker_lr_swap != reverse_speakers) {
4239 adev->speaker_lr_swap = reverse_speakers;
4240 // only update the selected device if there is active pcm playback
4241 struct audio_usecase *usecase;
4242 struct listnode *node;
4243 list_for_each(node, &adev->usecase_list) {
4244 usecase = node_to_item(node, struct audio_usecase, list);
4245 if (usecase->type == PCM_PLAYBACK) {
4246 select_devices(adev, usecase->id);
4247 break;
4248 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004249 }
4250 }
4251 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004252 }
4253
Mingming Yin514a8bc2014-07-29 15:22:21 -07004254 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4255 if (ret >= 0) {
4256 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4257 adev->bt_wb_speech_enabled = true;
4258 else
4259 adev->bt_wb_speech_enabled = false;
4260 }
4261
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4263 if (ret >= 0) {
4264 val = atoi(value);
4265 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004266 ALOGV("cache new ext disp type and edid");
4267 ret = platform_get_ext_disp_type(adev->platform);
4268 if (ret < 0) {
4269 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004270 status = ret;
4271 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004272 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004273 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004274 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004275 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004276 /*
4277 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4278 * Per AudioPolicyManager, USB device is higher priority than WFD.
4279 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4280 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4281 * starting voice call on USB
4282 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004283 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4284 if (ret >= 0) {
4285 audio_extn_usb_add_device(val, atoi(value));
4286 }
vivek mehta344576a2016-04-12 18:56:03 -07004287 ALOGV("detected USB connect .. disable proxy");
4288 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004289 }
4290 }
4291
4292 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4293 if (ret >= 0) {
4294 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004295 /*
4296 * The HDMI / Displayport disconnect handling has been moved to
4297 * audio extension to ensure that its parameters are not
4298 * invalidated prior to updating sysfs of the disconnect event
4299 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4300 */
4301 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004302 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004303 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4304 if (ret >= 0) {
4305 audio_extn_usb_remove_device(val, atoi(value));
4306 }
vivek mehta344576a2016-04-12 18:56:03 -07004307 ALOGV("detected USB disconnect .. enable proxy");
4308 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004309 }
4310 }
4311
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304312 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4313 if (ret >= 0) {
4314 struct audio_usecase *usecase;
4315 struct listnode *node;
4316 list_for_each(node, &adev->usecase_list) {
4317 usecase = node_to_item(node, struct audio_usecase, list);
4318 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004319 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304320 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304321 lock_output_stream(usecase->stream.out);
4322 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304323 //force device switch to re configure encoder
4324 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304325 audio_extn_a2dp_set_handoff_mode(false);
4326 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304327 break;
4328 }
4329 }
4330 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304331 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004332done:
4333 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004334 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304335error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004336 ALOGV("%s: exit with code(%d)", __func__, status);
4337 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338}
4339
4340static char* adev_get_parameters(const struct audio_hw_device *dev,
4341 const char *keys)
4342{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004343 struct audio_device *adev = (struct audio_device *)dev;
4344 struct str_parms *reply = str_parms_create();
4345 struct str_parms *query = str_parms_create_str(keys);
4346 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304347 char value[256] = {0};
4348 int ret = 0;
4349
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004350 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004351 if (reply) {
4352 str_parms_destroy(reply);
4353 }
4354 if (query) {
4355 str_parms_destroy(query);
4356 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004357 ALOGE("adev_get_parameters: failed to create query or reply");
4358 return NULL;
4359 }
4360
Naresh Tannirud7205b62014-06-20 02:54:48 +05304361 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4362 sizeof(value));
4363 if (ret >=0) {
4364 int val = 1;
4365 pthread_mutex_lock(&adev->snd_card_status.lock);
4366 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4367 val = 0;
4368 pthread_mutex_unlock(&adev->snd_card_status.lock);
4369 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4370 goto exit;
4371 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004372
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004373 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004374 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004375 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004376 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304377 pthread_mutex_unlock(&adev->lock);
4378
Naresh Tannirud7205b62014-06-20 02:54:48 +05304379exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004380 str = str_parms_to_str(reply);
4381 str_parms_destroy(query);
4382 str_parms_destroy(reply);
4383
4384 ALOGV("%s: exit: returns - %s", __func__, str);
4385 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386}
4387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004388static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004389{
4390 return 0;
4391}
4392
4393static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4394{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004395 int ret;
4396 struct audio_device *adev = (struct audio_device *)dev;
4397 pthread_mutex_lock(&adev->lock);
4398 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004399 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004400 pthread_mutex_unlock(&adev->lock);
4401 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402}
4403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004404static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4405 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
4407 return -ENOSYS;
4408}
4409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004410static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4411 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412{
4413 return -ENOSYS;
4414}
4415
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004416static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4417 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418{
4419 return -ENOSYS;
4420}
4421
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004422static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4423 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424{
4425 return -ENOSYS;
4426}
4427
4428static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4429{
4430 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 pthread_mutex_lock(&adev->lock);
4433 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004434 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004436 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004437 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004438 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004439 adev->current_call_output = NULL;
4440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 }
4442 pthread_mutex_unlock(&adev->lock);
4443 return 0;
4444}
4445
4446static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4447{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004448 int ret;
4449
4450 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004451 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004452 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4453 pthread_mutex_unlock(&adev->lock);
4454
4455 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456}
4457
4458static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4459{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004460 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 return 0;
4462}
4463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004464static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 const struct audio_config *config)
4466{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004467 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004469 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4470 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471}
4472
4473static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004474 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 audio_devices_t devices,
4476 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004477 struct audio_stream_in **stream_in,
4478 audio_input_flags_t flags __unused,
4479 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004480 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481{
4482 struct audio_device *adev = (struct audio_device *)dev;
4483 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004484 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004485 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004486 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304487 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304490 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4491 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004494
4495 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004496
4497 if (!in) {
4498 ALOGE("failed to allocate input stream");
4499 return -ENOMEM;
4500 }
4501
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304502 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304503 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4504 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004505 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004506 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 in->stream.common.get_sample_rate = in_get_sample_rate;
4509 in->stream.common.set_sample_rate = in_set_sample_rate;
4510 in->stream.common.get_buffer_size = in_get_buffer_size;
4511 in->stream.common.get_channels = in_get_channels;
4512 in->stream.common.get_format = in_get_format;
4513 in->stream.common.set_format = in_set_format;
4514 in->stream.common.standby = in_standby;
4515 in->stream.common.dump = in_dump;
4516 in->stream.common.set_parameters = in_set_parameters;
4517 in->stream.common.get_parameters = in_get_parameters;
4518 in->stream.common.add_audio_effect = in_add_audio_effect;
4519 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4520 in->stream.set_gain = in_set_gain;
4521 in->stream.read = in_read;
4522 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4523
4524 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004525 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 in->standby = 1;
4528 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004529 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004530 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531
4532 /* Update config params with the requested sample rate and channels */
4533 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004534 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4535 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4536 is_low_latency = true;
4537#if LOW_LATENCY_CAPTURE_USE_CASE
4538 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4539#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004540 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004541 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004542
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004543 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004544 if (in->realtime) {
4545 in->config = pcm_config_audio_capture_rt;
4546 in->sample_rate = in->config.rate;
4547 in->af_period_multiplier = af_period_multiplier;
4548 } else {
4549 in->config = pcm_config_audio_capture;
4550 in->config.rate = config->sample_rate;
4551 in->sample_rate = config->sample_rate;
4552 in->af_period_multiplier = 1;
4553 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304554 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004556 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304557 if (adev->mode != AUDIO_MODE_IN_CALL) {
4558 ret = -EINVAL;
4559 goto err_open;
4560 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004561 if (config->sample_rate == 0)
4562 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4563 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4564 config->sample_rate != 8000) {
4565 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4566 ret = -EINVAL;
4567 goto err_open;
4568 }
4569 if (config->format == AUDIO_FORMAT_DEFAULT)
4570 config->format = AUDIO_FORMAT_PCM_16_BIT;
4571 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4572 config->format = AUDIO_FORMAT_PCM_16_BIT;
4573 ret = -EINVAL;
4574 goto err_open;
4575 }
4576
4577 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4578 in->config = pcm_config_afe_proxy_record;
4579 in->config.channels = channel_count;
4580 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304581 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304582 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4583 in, config, &channel_mask_updated)) {
4584 if (channel_mask_updated == true) {
4585 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4586 __func__, config->channel_mask);
4587 ret = -EINVAL;
4588 goto err_open;
4589 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304590 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004591 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004592 audio_extn_compr_cap_format_supported(config->format) &&
4593 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004594 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004595 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304596 /* restrict 24 bit capture for unprocessed source only
4597 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4598 */
4599 if (config->format == AUDIO_FORMAT_DEFAULT) {
4600 config->format = AUDIO_FORMAT_PCM_16_BIT;
4601 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4602 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4603 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4604 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4605 bool ret_error = false;
4606 in->bit_width = 24;
4607 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4608 from HAL is 24_packed and 8_24
4609 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4610 24_packed return error indicating supported format is 24_packed
4611 *> In case of any other source requesting 24 bit or float return error
4612 indicating format supported is 16 bit only.
4613
4614 on error flinger will retry with supported format passed
4615 */
4616 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4617 (source != AUDIO_SOURCE_CAMCORDER)) {
4618 config->format = AUDIO_FORMAT_PCM_16_BIT;
4619 if( config->sample_rate > 48000)
4620 config->sample_rate = 48000;
4621 ret_error = true;
4622 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4623 in->config.format = PCM_FORMAT_S24_3LE;
4624 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4625 in->config.format = PCM_FORMAT_S24_LE;
4626 } else {
4627 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4628 ret_error = true;
4629 }
4630
4631 if (ret_error) {
4632 ret = -EINVAL;
4633 goto err_open;
4634 }
4635 }
4636
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004637 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004638 if (!in->realtime) {
4639 in->format = config->format;
4640 frame_size = audio_stream_in_frame_size(&in->stream);
4641 buffer_size = get_input_buffer_size(config->sample_rate,
4642 config->format,
4643 channel_count,
4644 is_low_latency);
4645 in->config.period_size = buffer_size / frame_size;
4646 }
4647
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004648 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4649 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4650 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004651 (in->config.rate == 8000 || in->config.rate == 16000 ||
4652 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004653 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4654 voice_extn_compress_voip_open_input_stream(in);
4655 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004658 /* This stream could be for sound trigger lab,
4659 get sound trigger pcm if present */
4660 audio_extn_sound_trigger_check_and_get_session(in);
4661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004664 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665
4666err_open:
4667 free(in);
4668 *stream_in = NULL;
4669 return ret;
4670}
4671
4672static void adev_close_input_stream(struct audio_hw_device *dev,
4673 struct audio_stream_in *stream)
4674{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004675 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004676 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004677 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304678
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304679 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004680
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304681 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004682 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304683
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004684 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304685 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004686 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304687 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004688 if (ret != 0)
4689 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4690 __func__, ret);
4691 } else
4692 in_standby(&stream->common);
4693
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004694 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004695 audio_extn_ssr_deinit();
4696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697
Mingming Yine62d7842013-10-25 16:26:03 -07004698 if(audio_extn_compr_cap_enabled() &&
4699 audio_extn_compr_cap_format_supported(in->config.format))
4700 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004701
Mingming Yinfd7607b2016-01-22 12:48:44 -08004702 if (in->is_st_session) {
4703 ALOGV("%s: sound trigger pcm stop lab", __func__);
4704 audio_extn_sound_trigger_stop_lab(in);
4705 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004706 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 return;
4708}
4709
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004710static int adev_dump(const audio_hw_device_t *device __unused,
4711 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712{
4713 return 0;
4714}
4715
4716static int adev_close(hw_device_t *device)
4717{
4718 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004719
4720 if (!adev)
4721 return 0;
4722
4723 pthread_mutex_lock(&adev_init_lock);
4724
4725 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004726 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004727 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304728 if (audio_extn_qaf_is_enabled())
4729 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004730 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004731 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004732 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004733 free(adev->snd_dev_ref_cnt);
4734 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004735 if (adev->adm_deinit)
4736 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004737 free(device);
4738 adev = NULL;
4739 }
4740 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 return 0;
4743}
4744
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004745/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4746 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4747 * just that it _might_ work.
4748 */
4749static int period_size_is_plausible_for_low_latency(int period_size)
4750{
4751 switch (period_size) {
4752 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004753 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004754 case 240:
4755 case 320:
4756 case 480:
4757 return 1;
4758 default:
4759 return 0;
4760 }
4761}
4762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763static int adev_open(const hw_module_t *module, const char *name,
4764 hw_device_t **device)
4765{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304766 int ret;
4767
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004768 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4770
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004771 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004772 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004773 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004774 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004775 ALOGD("%s: returning existing instance of adev", __func__);
4776 ALOGD("%s: exit", __func__);
4777 pthread_mutex_unlock(&adev_init_lock);
4778 return 0;
4779 }
4780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 adev = calloc(1, sizeof(struct audio_device));
4782
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004783 if (!adev) {
4784 pthread_mutex_unlock(&adev_init_lock);
4785 return -ENOMEM;
4786 }
4787
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004788 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4791 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4792 adev->device.common.module = (struct hw_module_t *)module;
4793 adev->device.common.close = adev_close;
4794
4795 adev->device.init_check = adev_init_check;
4796 adev->device.set_voice_volume = adev_set_voice_volume;
4797 adev->device.set_master_volume = adev_set_master_volume;
4798 adev->device.get_master_volume = adev_get_master_volume;
4799 adev->device.set_master_mute = adev_set_master_mute;
4800 adev->device.get_master_mute = adev_get_master_mute;
4801 adev->device.set_mode = adev_set_mode;
4802 adev->device.set_mic_mute = adev_set_mic_mute;
4803 adev->device.get_mic_mute = adev_get_mic_mute;
4804 adev->device.set_parameters = adev_set_parameters;
4805 adev->device.get_parameters = adev_get_parameters;
4806 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4807 adev->device.open_output_stream = adev_open_output_stream;
4808 adev->device.close_output_stream = adev_close_output_stream;
4809 adev->device.open_input_stream = adev_open_input_stream;
4810 adev->device.close_input_stream = adev_close_input_stream;
4811 adev->device.dump = adev_dump;
4812
4813 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004815 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004816 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004819 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004820 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004821 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004822 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004823 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004824 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004825 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004826 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304827 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304828 adev->perf_lock_opts[0] = 0x101;
4829 adev->perf_lock_opts[1] = 0x20E;
4830 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304831
4832 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4833 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004835 adev->platform = platform_init(adev);
4836 if (!adev->platform) {
4837 free(adev->snd_dev_ref_cnt);
4838 free(adev);
4839 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4840 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004841 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304842 pthread_mutex_destroy(&adev->lock);
4843 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004844 return -EINVAL;
4845 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004846
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304847 if (audio_extn_qaf_is_enabled()) {
4848 ret = audio_extn_qaf_init(adev);
4849 if (ret < 0) {
4850 free(adev);
4851 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4852 *device = NULL;
4853 pthread_mutex_unlock(&adev_init_lock);
4854 pthread_mutex_destroy(&adev->lock);
4855 return ret;
4856 }
4857
4858 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4859 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4860 }
4861
Naresh Tanniru4c630392014-05-12 01:05:52 +05304862 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4863
Eric Laurentc4aef752013-09-12 17:45:53 -07004864 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4865 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4866 if (adev->visualizer_lib == NULL) {
4867 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4868 } else {
4869 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4870 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004871 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004872 "visualizer_hal_start_output");
4873 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004874 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004875 "visualizer_hal_stop_output");
4876 }
4877 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004878 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004879 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004880 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004881
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004882 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4883 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4884 if (adev->offload_effects_lib == NULL) {
4885 ALOGE("%s: DLOPEN failed for %s", __func__,
4886 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4887 } else {
4888 ALOGV("%s: DLOPEN successful for %s", __func__,
4889 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4890 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304891 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004892 "offload_effects_bundle_hal_start_output");
4893 adev->offload_effects_stop_output =
4894 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4895 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004896 adev->offload_effects_set_hpx_state =
4897 (int (*)(bool))dlsym(adev->offload_effects_lib,
4898 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304899 adev->offload_effects_get_parameters =
4900 (void (*)(struct str_parms *, struct str_parms *))
4901 dlsym(adev->offload_effects_lib,
4902 "offload_effects_bundle_get_parameters");
4903 adev->offload_effects_set_parameters =
4904 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4905 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004906 }
4907 }
4908
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004909 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4910 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4911 if (adev->adm_lib == NULL) {
4912 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4913 } else {
4914 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4915 adev->adm_init = (adm_init_t)
4916 dlsym(adev->adm_lib, "adm_init");
4917 adev->adm_deinit = (adm_deinit_t)
4918 dlsym(adev->adm_lib, "adm_deinit");
4919 adev->adm_register_input_stream = (adm_register_input_stream_t)
4920 dlsym(adev->adm_lib, "adm_register_input_stream");
4921 adev->adm_register_output_stream = (adm_register_output_stream_t)
4922 dlsym(adev->adm_lib, "adm_register_output_stream");
4923 adev->adm_deregister_stream = (adm_deregister_stream_t)
4924 dlsym(adev->adm_lib, "adm_deregister_stream");
4925 adev->adm_request_focus = (adm_request_focus_t)
4926 dlsym(adev->adm_lib, "adm_request_focus");
4927 adev->adm_abandon_focus = (adm_abandon_focus_t)
4928 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004929 adev->adm_set_config = (adm_set_config_t)
4930 dlsym(adev->adm_lib, "adm_set_config");
4931 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4932 dlsym(adev->adm_lib, "adm_request_focus_v2");
4933 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4934 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4935 adev->adm_on_routing_change = (adm_on_routing_change_t)
4936 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004937 }
4938 }
4939
Mingming Yin514a8bc2014-07-29 15:22:21 -07004940 adev->bt_wb_speech_enabled = false;
4941
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004942 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943 *device = &adev->device.common;
4944
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004945 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4946 &adev->streams_output_cfg_list);
4947
Kiran Kandi910e1862013-10-29 13:29:42 -07004948 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004949
4950 char value[PROPERTY_VALUE_MAX];
4951 int trial;
4952 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4953 trial = atoi(value);
4954 if (period_size_is_plausible_for_low_latency(trial)) {
4955 pcm_config_low_latency.period_size = trial;
4956 pcm_config_low_latency.start_threshold = trial / 4;
4957 pcm_config_low_latency.avail_min = trial / 4;
4958 configured_low_latency_capture_period_size = trial;
4959 }
4960 }
4961 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4962 trial = atoi(value);
4963 if (period_size_is_plausible_for_low_latency(trial)) {
4964 configured_low_latency_capture_period_size = trial;
4965 }
4966 }
4967
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004968 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4969 af_period_multiplier = atoi(value);
4970 if (af_period_multiplier < 0)
4971 af_period_multiplier = 2;
4972 else if (af_period_multiplier > 4)
4973 af_period_multiplier = 4;
4974
4975 ALOGV("new period_multiplier = %d", af_period_multiplier);
4976 }
4977
vivek mehta446c3962015-09-14 10:57:35 -07004978 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004979 pthread_mutex_unlock(&adev_init_lock);
4980
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004981 if (adev->adm_init)
4982 adev->adm_data = adev->adm_init();
4983
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304984 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004985 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986 return 0;
4987}
4988
4989static struct hw_module_methods_t hal_module_methods = {
4990 .open = adev_open,
4991};
4992
4993struct audio_module HAL_MODULE_INFO_SYM = {
4994 .common = {
4995 .tag = HARDWARE_MODULE_TAG,
4996 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4997 .hal_api_version = HARDWARE_HAL_API_VERSION,
4998 .id = AUDIO_HARDWARE_MODULE_ID,
4999 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005000 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001 .methods = &hal_module_methods,
5002 },
5003};